Was bedeutet Linus Torvalds, wenn er sagt, dass Git "nie" eine Datei verfolgt?

283

Zitat von Linus Torvalds auf die Frage, wie viele Dateien Git während seines Tech Talk bei Google 2007 (43:09) verarbeiten kann:

… Git verfolgt Ihren Inhalt. Es wird niemals eine einzelne Datei verfolgt. Sie können eine Datei in Git nicht verfolgen. Was Sie tun können, ist, dass Sie ein Projekt verfolgen können, das eine einzelne Datei enthält. Wenn Ihr Projekt jedoch eine einzelne Datei enthält, tun Sie dies auf jeden Fall und Sie können es tun. Wenn Sie jedoch 10.000 Dateien verfolgen, sieht Git diese niemals als einzelne Dateien an. Git denkt alles als vollen Inhalt. Die gesamte Geschichte in Git basiert auf der Geschichte des gesamten Projekts…

(Transkripte hier .)

Doch wenn man in taucht das Git Buch , das erste , was Sie gesagt werden , ist , dass eine Datei in Git kann entweder verfolgt oder untracked . Außerdem scheint mir das gesamte Git-Erlebnis auf die Versionierung von Dateien ausgerichtet zu sein. Bei Verwendung git diffoder git statusAusgabe wird pro Datei dargestellt. Bei der Verwendung können git addSie auch pro Datei auswählen. Sie können den Verlauf sogar auf Dateibasis überprüfen und sind blitzschnell.

Wie ist diese Aussage zu interpretieren? Wie unterscheidet sich Git in Bezug auf die Dateiverfolgung von anderen Versionsverwaltungssystemen wie CVS?

Simón Ramírez Amaya
quelle
20
reddit.com/r/git/comments/5xmrkv/what_is_a_snapshot_in_git - "Ich vermute , dass es wichtiger ist zu erkennen, dass es einen Unterschied gibt, wie Git Dateien Benutzern präsentiert und wie sie intern damit umgehen . Wie dem Benutzer präsentiert, enthält ein Snapshot vollständige Dateien, nicht nur Unterschiede. Intern verwendet Git jedoch Unterschiede, um Paketdateien zu generieren, in denen Revisionen effizient gespeichert werden. " (Dies ist ein scharfer Kontrast zu z. B. Subversion.)
user2864740
5
Git verfolgt keine Dateien, sondern Änderungssätze . Die meisten Versionskontrollsysteme verfolgen Dateien. Versuchen Sie als Beispiel, wie / warum dies wichtig sein kann, ein leeres Verzeichnis in git einzuchecken (spolier: Sie können nicht, da dies ein "leerer" Änderungssatz ist).
Elliott Frisch
12
@ElliottFrisch Das klingt nicht richtig. Ihre Beschreibung ist näher an dem, was zB darcs tut. Git speichert Schnappschüsse, keine Änderungssätze.
Melpomene
4
Ich denke, er meint, Git verfolgt eine Datei nicht direkt. Eine Datei enthält ihren Namen und Inhalt. Git verfolgt Inhalte als Blobs. Wenn nur ein Blob angegeben ist, können Sie den entsprechenden Dateinamen nicht erkennen. Dies kann der Inhalt mehrerer Dateien mit unterschiedlichen Namen unter verschiedenen Pfaden sein. Die Bindungen zwischen einem Pfadnamen und einem Blob werden in einem Baumobjekt beschrieben.
ElpieKay
3
Siehe auch: Randal Schwartz ' Follow - up zu Linus' Vortrag (auch ein Google Tech-Vortrag) - "... worum es bei Git wirklich geht ... Linus hat gesagt, was Git NICHT ist".
Peter Mortensen

Antworten:

316

In CVS wurde der Verlauf pro Datei verfolgt. Ein Zweig kann aus verschiedenen Dateien mit eigenen Revisionen bestehen, von denen jede ihre eigene Versionsnummer hat. CVS basierte auf RCS ( Revision Control System ), das einzelne Dateien auf ähnliche Weise verfolgte.

Auf der anderen Seite macht Git Schnappschüsse vom Status des gesamten Projekts. Dateien werden nicht unabhängig voneinander verfolgt und versioniert. Eine Revision im Repository bezieht sich auf einen Status des gesamten Projekts, nicht auf eine Datei.

Wenn Git sich auf das Verfolgen einer Datei bezieht, bedeutet dies einfach, dass sie in den Verlauf des Projekts aufgenommen werden soll. Linus 'Vortrag bezog sich nicht auf Tracking-Dateien im Git-Kontext, sondern stellte das CVS- und RCS-Modell dem in Git verwendeten Snapshot-basierten Modell gegenüber.

bk2204
quelle
4
Sie können hinzufügen, dass Sie aus diesem Grund in CVS und Subversion Tags wie $Id$in einer Datei verwenden können. Das gleiche funktioniert nicht in Git, weil das Design unterschiedlich ist.
Gerrit
58
Und der Inhalt ist nicht wie erwartet an eine Datei gebunden. Versuchen Sie, 80% des Codes einer Datei in eine andere zu verschieben. Git erkennt automatisch eine Dateiverschiebung + 20% Änderung, selbst wenn Sie gerade Code in vorhandenen Dateien verschoben haben.
Allo
13
@allo Als Nebeneffekt kann git eines tun, was die anderen nicht können: Wenn zwei Dateien zusammengeführt werden und Sie "git tad -C" verwenden, kann git beide Historien nachschlagen. Bei der dateibasierten Nachverfolgung müssen Sie auswählen, welche der Originaldateien das echte Original ist, und die anderen Zeilen erscheinen alle brandneu.
Izkata
1
@allo, Izkata - Und es ist die abfragende Entität , die all dies herausarbeitet, indem sie den Repo-Inhalt zur Abfragezeit analysiert (Commit-Historien und Unterschiede zwischen referenzierten Bäumen und Blobs), anstatt dass die Commit- Entität und ihr menschlicher Benutzer die korrekte Angabe oder Synthese vornehmen müssen Diese Informationen zum Zeitpunkt des Festschreibens - noch der Entwickler des Repo-Tools, der diese Funktion und das entsprechende Metadatenschema vor der Bereitstellung des Tools entwirft und implementiert. Torvalds argumentierte, dass eine solche Analyse mit der Zeit nur besser werden wird und die gesamte Geschichte jedes Git-Repos seit dem ersten Tag davon profitieren wird.
Jeremy
1
@allo Yep, und um die Tatsache zu verdeutlichen, dass Git auf Dateiebene nicht funktioniert, müssen Sie nicht einmal alle Änderungen in einer Datei auf einmal festschreiben. Sie können beliebige Zeilenbereiche festschreiben, während andere Änderungen in der Datei außerhalb des Festschreibens bleiben. Natürlich ist die Benutzeroberfläche dafür bei weitem nicht so einfach, so dass die meisten dies nicht tun, aber sie hat selten ihre Verwendung.
Alvin Thompson
103

Ich stimme brian m zu. Carlsons Antwort : Linus unterscheidet tatsächlich zumindest teilweise zwischen dateiorientierten und festschreibungsorientierten Versionskontrollsystemen. Aber ich denke, da steckt noch mehr dahinter.

Im meinem Buch , das ins Stocken gerät und möglicherweise nie fertig wird, habe ich versucht, eine Taxonomie für Versionskontrollsysteme zu entwickeln. In meiner Taxonomie ist der Begriff für das, was uns hier interessiert, die Atomizität des Versionskontrollsystems. Weitere Informationen finden Sie auf Seite 22. Wenn ein VCS eine Atomizität auf Dateiebene aufweist, gibt es tatsächlich einen Verlauf für jede Datei. Das VCS muss sich den Namen der Datei und die Ereignisse an jedem Punkt merken.

Git macht das nicht. Git hat nur eine Geschichte von Commits - das Commit ist seine Einheit der Atomizität, und die Geschichte ist die Menge der Commits im Repository. Was sich ein Commit merkt, sind die Daten - ein ganzer Baum voller Dateinamen und der Inhalte, die zu jeder dieser Dateien gehören - sowie einige Metadaten: Zum Beispiel, wer das Commit durchgeführt hat, wann und warum und die interne Git-Hash-ID des übergeordneten Commits des Commits. (Es ist dieses übergeordnete Element und das gerichtete Acycling-Diagramm, das durch Lesen aller Commits und ihrer übergeordneten Elemente erstellt wurde. Dies ist der Verlauf in einem Repository.)

Beachten Sie, dass ein VCS festschreibungsorientiert sein kann und dennoch Daten Datei für Datei speichert. Das ist ein Implementierungsdetail, wenn auch manchmal ein wichtiges, und Git macht das auch nicht. Stattdessen jeder Commit Datensätze einen Baum , mit den Baum Objektcodierung Dateinamen , Betriebsart (dh, diese ausführbare Datei oder nicht?), Und ein Zeiger auf den tatsächlichen Dateiinhalt . Der Inhalt selbst wird unabhängig in einem Blob-Objekt gespeichert . Wie ein Commit-Objekt erhält ein Blob eine Hash-ID, die für seinen Inhalt eindeutig ist. Im Gegensatz zu einem Commit, das nur einmal angezeigt werden kann, kann der Blob jedoch in vielen Commits angezeigt werden. Der zugrunde liegende Dateiinhalt in Git wird also direkt als Blob und dann indirekt gespeichert in einem Baumobjekt, dessen Hash-ID (direkt oder indirekt) im Festschreibungsobjekt aufgezeichnet ist.

Wenn Sie Git bitten, Ihnen den Verlauf einer Datei anzuzeigen, indem Sie:

git log [--follow] [starting-point] [--] path/to/file

was Git wirklich tut das ist zu Fuß begehen Geschichte, die die einzige Geschichte Git ist, aber nicht zeigen Sie eine dieser Commits , es sei denn:

  • Das Commit ist ein Nicht-Merge-Commit
  • Das übergeordnete Element dieses Commits verfügt ebenfalls über die Datei, der Inhalt des übergeordneten Commits ist jedoch unterschiedlich, oder das übergeordnete Element des Commits verfügt überhaupt nicht über die Datei

(Einige dieser Bedingungen können jedoch über zusätzliche git logOptionen geändert werden , und es gibt einen sehr schwer zu beschreibenden Nebeneffekt namens "History Simplification", der dazu führt, dass Git einige Commits vollständig aus dem History Walk auslässt.) Der hier angezeigte Dateiversionsverlauf ist in gewissem Sinne nicht genau im Repository vorhanden. Stattdessen handelt es sich nur um eine synthetische Teilmenge des tatsächlichen Verlaufs. Sie erhalten einen anderen "Dateiversionsverlauf", wenn Sie verschiedene git logOptionen verwenden!

torek
quelle
Eine andere Sache, die hinzugefügt werden muss, ist, dass Git Dinge wie flache Klone tun kann. Es muss nur das Head-Commit und alle Blobs abgerufen werden, auf die es sich bezieht. Es müssen keine Dateien durch Anwenden von Änderungssätzen neu erstellt werden.
Wes Toleman
@WesToleman: Das macht es definitiv einfacher. Mercurial speichert Deltas mit gelegentlichen Zurücksetzungen, und während die Mercurial-Leute beabsichtigen, dort flache Klone hinzuzufügen (was aufgrund der Idee des "Zurücksetzens" möglich ist), haben sie dies noch nicht getan (weil es eher eine technische Herausforderung ist).
Torek
@torek Ich habe Zweifel an Ihrer Beschreibung, wie Git eine Dateiverlaufsanfrage beantwortet, aber ich denke, sie verdient ihre eigene richtige Frage: stackoverflow.com/questions/55616349/…
Simón Ramírez Amaya
@torek Danke für den Link zu deinem Buch, ich habe nichts Vergleichbares gesehen.
gnarledRoot
17

Das verwirrende Stück ist hier:

Git sieht diese niemals als einzelne Dateien. Git denkt alles als vollen Inhalt.

Git verwendet häufig 160-Bit-Hashes anstelle von Objekten in seinem eigenen Repo. Ein Dateibaum ist im Grunde eine Liste von Namen und Hashes, die dem jeweiligen Inhalt zugeordnet sind (plus einige Metadaten).

Der 160-Bit-Hash identifiziert den Inhalt jedoch eindeutig (innerhalb des Universums der Git-Datenbank). Ein Baum mit Hashes als Inhalt enthält also den Inhalt in seinem Zustand.

Wenn Sie den Status des Inhalts einer Datei ändern, ändert sich ihr Hash. Wenn sich jedoch der Hash ändert, ändert sich auch der mit dem Inhalt des Dateinamens verknüpfte Hash. Was wiederum den Hash des "Verzeichnisbaums" ändert.

Wenn eine Git-Datenbank einen Verzeichnisbaum speichert, impliziert und enthält dieser Verzeichnisbaum den gesamten Inhalt aller Unterverzeichnisse und aller darin enthaltenen Dateien .

Es ist in einer Baumstruktur mit (unveränderlichen, wiederverwendbaren) Zeigern auf Blobs oder andere Bäume organisiert, aber logischerweise ist es eine einzelne Momentaufnahme des gesamten Inhalts des gesamten Baums. Die Darstellung in der Git-Datenbank ist nicht der flache Dateninhalt, sondern logischerweise alle Daten und sonst nichts.

Wenn Sie den Baum in ein Dateisystem serialisiert, alle .git-Ordner gelöscht und git angewiesen haben, den Baum wieder in die Datenbank aufzunehmen, wird der Datenbank am Ende nichts hinzugefügt - das Element wäre bereits vorhanden.

Es kann hilfreich sein, sich Git-Hashes als Referenzzähler auf unveränderliche Daten vorzustellen.

Wenn Sie eine Anwendung darauf erstellt haben, besteht ein Dokument aus mehreren Seiten mit Ebenen, Gruppen und Objekten.

Wenn Sie ein Objekt ändern möchten, müssen Sie eine völlig neue Gruppe dafür erstellen. Wenn Sie eine Gruppe ändern möchten, müssen Sie eine neue Ebene erstellen, für die eine neue Seite und ein neues Dokument erforderlich ist.

Jedes Mal, wenn Sie ein einzelnes Objekt ändern, wird ein neues Dokument erstellt. Das alte Dokument bleibt bestehen. Das neue und das alte Dokument teilen den größten Teil ihres Inhalts - sie haben dieselben Seiten (außer 1). Diese eine Seite hat die gleichen Ebenen (außer 1). Diese Schicht hat die gleichen Gruppen (außer 1). Diese Gruppe hat dieselben Objekte (außer 1).

Und damit meine ich logischerweise eine Kopie, aber in Bezug auf die Implementierung ist es nur ein weiterer Zeiger mit Referenzzählung auf dasselbe unveränderliche Objekt.

Ein Git Repo ist sehr ähnlich.

Dies bedeutet, dass ein bestimmtes Git-Änderungsset seine Festschreibungsnachricht (als Hash-Code), seinen Arbeitsbaum und seine übergeordneten Änderungen enthält.

Diese übergeordneten Änderungen enthalten die übergeordneten Änderungen auf dem gesamten Rückweg.

Der Teil des Git-Repos, der die Geschichte enthält, ist diese Kette von Änderungen. Diese Änderungskette befindet sich auf einer Ebene oberhalb des "Verzeichnis" -Baums. Von einem "Verzeichnis" -Baum aus können Sie nicht eindeutig zu einem Änderungssatz und der Änderungskette gelangen.

Um herauszufinden, was mit einer Datei passiert, beginnen Sie mit dieser Datei in einem Änderungssatz. Dieser Änderungssatz hat eine Geschichte. Oft existiert in diesem Verlauf dieselbe benannte Datei, manchmal mit demselben Inhalt. Wenn der Inhalt identisch ist, wurde die Datei nicht geändert. Wenn es anders ist, gibt es eine Änderung, und es muss gearbeitet werden, um genau herauszufinden, was.

Manchmal ist die Datei weg; Der "Verzeichnis" -Baum enthält jedoch möglicherweise eine andere Datei mit demselben Inhalt (demselben Hash-Code), sodass wir ihn auf diese Weise verfolgen können (Hinweis: Aus diesem Grund möchten Sie, dass ein Commit-to-Move eine von einem Commit-to getrennte Datei verschiebt -bearbeiten). Oder der gleiche Dateiname, und nach dem Überprüfen ist die Datei ähnlich genug.

So kann git einen "Dateiverlauf" zusammenfügen.

Dieser Dateiversionsverlauf stammt jedoch aus dem effizienten Parsen des "gesamten Änderungssatzes" und nicht aus einem Link von einer Version der Datei zu einer anderen.

Yakk - Adam Nevraumont
quelle
12

"git verfolgt keine Dateien" bedeutet im Grunde, dass die Commits von git aus einem Dateibaum-Snapshot bestehen, der einen Pfad im Baum mit einem "Blob" verbindet, und einem Commit-Diagramm, das den Verlauf der Commits verfolgt . Alles andere wird im laufenden Betrieb durch Befehle wie "Git Log" und "Git Blame" rekonstruiert. Diese Rekonstruktion kann über verschiedene Optionen festgelegt werden, wie schwierig es sein sollte, nach dateibasierten Änderungen zu suchen. Die Standardheuristik kann bestimmen, wann ein Blob die Position im Dateibaum ohne Änderung ändert oder wann eine Datei einem anderen Blob als zuvor zugeordnet ist. Die von Git verwendeten Komprimierungsmechanismen kümmern sich nicht viel um Blob- / Dateigrenzen. Wenn sich der Inhalt bereits irgendwo befindet, wird das Repository-Wachstum dadurch klein gehalten, ohne dass die verschiedenen Blobs zugeordnet werden.

Das ist das Repository. Git hat auch einen Arbeitsbaum, und in diesem Arbeitsbaum gibt es verfolgte und nicht verfolgte Dateien. Nur die verfolgten Dateien werden im Index aufgezeichnet (Staging-Bereich? Cache?) Und nur das, was dort verfolgt wird, gelangt in das Repository.

Der Index ist dateiorientiert und es gibt einige dateiorientierte Befehle zum Bearbeiten. Was jedoch im Repository landet, sind Commits in Form von Dateibaum-Snapshots und den zugehörigen Blob-Daten sowie den Vorfahren des Commits.

Da Git keine Dateiversionen und Umbenennungen verfolgt und deren Effizienz nicht von diesen abhängt, müssen Sie es manchmal einige Male mit verschiedenen Optionen versuchen, bis Git die Historie / Unterschiede / Schuldzuweisungen erstellt, an denen Sie für nicht triviale Historien interessiert sind.

Das ist anders bei Systemen wie Subversion, die eher aufzeichnen als rekonstruieren Historien . Wenn es nicht aufgezeichnet ist, können Sie nichts davon hören.

Ich habe tatsächlich einmal ein Differential-Installationsprogramm erstellt, das nur Release-Bäume verglichen hat, indem ich sie in Git eingecheckt und dann ein Skript erstellt habe, das ihre Wirkung dupliziert. Da manchmal ganze Bäume verschoben wurden, führte dies zu viel kleineren Differentialinstallationsprogrammen als das Überschreiben / Löschen von allem.


quelle
7

Git verfolgt eine Datei nicht direkt, sondern Snapshots des Repositorys, und diese Snapshots bestehen zufällig aus Dateien.

Hier ist eine Möglichkeit, es zu betrachten.

In anderen Versionskontrollsystemen (SVN, Rational ClearCase) können Sie mit der rechten Maustaste auf eine Datei klicken und deren Änderungsverlauf abrufen .

In Git gibt es keinen direkten Befehl, der dies tut. Siehe diese Frage . Sie werden überrascht sein, wie viele verschiedene Antworten es gibt. Es gibt keine einfache Antwort, da Git eine Datei nicht einfach nachverfolgt , nicht so, wie es SVN oder ClearCase tun.

Double Vision Stout Fat Heavy
quelle
5
Ich glaube, ich verstehe, was Sie sagen wollen, aber "In Git gibt es keinen direkten Befehl, der dies tut" wird durch die Antworten auf die Frage, mit der Sie verknüpft sind, direkt widersprochen. Zwar erfolgt die Versionierung auf der Ebene des gesamten Repositorys, doch gibt es in Git normalerweise viele Möglichkeiten, um etwas zu erreichen. Mehrere Befehle zum Anzeigen des Dateiversionsverlaufs sind also kein Beweis für viel.
Joe Lee-Moyet
Ich habe die ersten Antworten auf die von Ihnen verknüpfte Frage überflogen und alle verwenden git logoder ein darauf aufbauendes Programm (oder einen Alias, der dasselbe tut). Aber selbst wenn es viele verschiedene Möglichkeiten gäbe, wie Joe sagt, gilt dies auch für die Darstellung der Branchengeschichte. ( git log -p <file>ist auch eingebaut und macht genau das)
Voo
Sind Sie sicher, dass SVN Änderungen pro Datei intern speichert? Ich habe es schon seit einiger Zeit nicht mehr verwendet, aber ich erinnere mich vage daran, dass Dateien wie Versions-IDs benannt wurden, anstatt die Struktur der Projektdatei widerzuspiegeln.
Artur Biesiadowski
3

Das Verfolgen von "Inhalten" führte übrigens dazu, dass leere Verzeichnisse nicht verfolgt wurden.
Wenn Sie die letzte Datei eines Ordners eingeben, wird der Ordner selbst gelöscht .

Dies war nicht immer der Fall, und nur Git 1.4 (Mai 2006) hat diese Richtlinie zum Verfolgen von Inhalten mit Commit 443f833 durchgesetzt :

Git-Status: Überspringen Sie leere Verzeichnisse und fügen Sie -u hinzu, um alle nicht verfolgten Dateien anzuzeigen

Standardmäßig werden --others --directoryuninteressante Verzeichnisse angezeigt (um die Aufmerksamkeit des Benutzers zu erregen), ohne deren Inhalt (um die Ausgabe übersichtlicher zu gestalten).
Das Anzeigen leerer Verzeichnisse ist nicht sinnvoll. Übergeben Sie dies, --no-empty-directorywenn wir dies tun.

Durch Geben -u(oder --untracked) wird diese Übersichtlichkeit deaktiviert, damit der Benutzer alle nicht verfolgten Dateien abrufen kann.

Dies wurde Jahre später im Januar 2011 mit Commit 8fe533 , Git v1.7.4 wiederholt:

Dies steht im Einklang mit der allgemeinen UI-Philosophie: git verfolgt Inhalte, keine leeren Verzeichnisse.

In der Zwischenzeit beginnt Git mit Git 1.4.3 (Sept. 2006), nicht verfolgten Inhalt mit Commit 2074cb0 auf nicht leere Ordner zu beschränken :

Es sollte nicht den Inhalt vollständig nicht verfolgter Verzeichnisse auflisten, sondern nur den Namen dieses Verzeichnisses (plus ein abschließendes ' /').

Das Verfolgen von Inhalten hat es Git erlaubt, sehr früh (Git 1.4.4, Okt. 2006, Commit cee7f24 ) die Schuld zu geben :

Noch wichtiger ist, dass die interne Struktur die Bewegung von Inhalten (auch als Ausschneiden und Einfügen bezeichnet) einfacher unterstützt, indem mehr als ein Pfad aus demselben Commit entnommen werden kann.

Dies (Tracking-Inhalt) ist auch das, was git in die Git-API mit Git 1.5.0 (Dez. 2006, Commit 366bfcb ) einfügt.

Machen Sie 'git add' zu einer erstklassigen benutzerfreundlichen Oberfläche für den Index

Dies bringt die Kraft des Index nach vorne, indem ein geeignetes mentales Modell verwendet wird, ohne überhaupt über den Index zu sprechen.
Sehen Sie zum Beispiel, wie die gesamte technische Diskussion von der git-add-Manpage entfernt wurde.

Alle festzuschreibenden Inhalte müssen zusammengefügt werden.
Ob dieser Inhalt aus neuen oder geänderten Dateien stammt, spielt keine Rolle.
Sie müssen es nur "hinzufügen", entweder mit git-add oder indem Sie git-commit mit bereitstellen -a(natürlich nur für bereits bekannte Dateien).

Das ist , was gemacht git add --interactivemöglich, mit der gleichen Git 1.5.0 ( commit 5cde71d )

Antworten Sie nach der Auswahl mit einer leeren Zeile, um den Inhalt der Arbeitsbaumdateien für ausgewählte Pfade im Index bereitzustellen.

Aus diesem Grund müssen Sie zum rekursiven Entfernen aller Inhalte aus einem Verzeichnis die -rOption übergeben, nicht nur den Verzeichnisnamen als <path>(immer noch Git 1.5.0, Commit 9f95069 ).

Das Anzeigen des Dateiinhalts anstelle der Datei selbst ermöglicht ein Zusammenführungsszenario wie das in Commit 1de70db (Git v2.18.0-rc0, April 2018) beschriebene.

Betrachten Sie die folgende Zusammenführung mit einem Umbenennungs- / Hinzufügenkonflikt:

  • Seite A: ändern foo, nicht verwandt hinzufügenbar
  • Seite B: Umbenennen foo->bar(aber den Modus oder Inhalt nicht ändern)

In diesem Fall ist der Drei-Wege - merge der ursprünglich foo, A die foo und B barwird in einem gewünschten Pfad des Ergebnis barmit dem gleichen Modus / Inhalt , dass A mußte foo.
Somit hatte A den richtigen Modus und Inhalt für die Datei und den richtigen Pfadnamen (nämlich bar).

Commit 37b65ce , Git v2.21.0-rc0, Dez. 2018, hat kürzlich die Lösung kollidierender Konflikte verbessert.
Und bbafc9c begehen firther verdeutlicht die Bedeutung Datei unter Berücksichtigung Inhalte , durch die Handhabung zu verbessern für Umbenennungs / Umbenennungs (2to1) Konflikte:

  • Anstatt Dateien bei collide_path~HEADund zu speichern collide_path~MERGE, werden die Dateien in beide Richtungen zusammengeführt und bei aufgezeichnet collide_path.
  • Anstatt die Version der umbenannten Datei, die auf der umbenannten Seite vorhanden war, im Index aufzuzeichnen (wodurch alle Änderungen ignoriert werden, die an der Datei auf der Seite des Verlaufs ohne Umbenennung vorgenommen wurden), führen wir eine Drei-Wege-Zusammenführung von Inhalten für die umbenannte Datei durch Pfad, dann speichern Sie diese entweder in Stufe 2 oder Stufe 3.
  • Beachten Sie, dass die Zusammenführung von Inhalten für jede Umbenennung zu Konflikten führen kann und wir dann die beiden umbenannten Dateien zusammenführen müssen. Dies kann zu verschachtelten Konfliktmarkierungen führen.
VonC
quelle