406 Stimmen

Was ist der Zweck von git-mv?

Soweit ich weiß, muss Git nicht wirklich die Datei Umbenennungs-/Verschiebungs-/Kopiervorgänge, was ist also der eigentliche Zweck von git mv ? Die Manpage ist nicht besonders aussagekräftig...

Ist sie veraltet? Handelt es sich um einen internen Befehl, der nicht von normalen Benutzern verwendet werden soll?

542voto

CB Bailey Punkte 693084
git mv oldname newname

ist nur eine Kurzform für:

mv oldname newname
git add newname
git rm oldname

d.h. er aktualisiert den Index für alte und neue Pfade automatisch.

55 Stimmen

Außerdem hat er einige Sicherheitsvorkehrungen eingebaut.

11 Stimmen

Danke @CharlesBailey - Betrachtet Git dann die Dateien newNameFile und oldNameFile als unterschiedlich? Wenn ja, was passiert, wenn wir sie zusammenführen wollen? Angenommen, wir verzweigen ein Ameisenprojekt auf Zweig A und erstellen Zweig B und mavenisieren dann die Projekte auf B. Die Dateinamen sind die gleichen, aber auf unterschiedlichen Pfaden, da sich die Projektstruktur geändert hat. Nehmen wir an, beide Zweige wuchsen eine Zeit lang parallel. Wenn wir irgendwann die Projekte zusammenführen wollen, woher weiß Git dann, dass es sich um dieselbe Datei handelt, deren Pfad nur umbenannt wurde? (wenn "git mv" == "git add + git rm")

0 Stimmen

Ich denke, es ist dasselbe, nur mit einer Wahrscheinlichkeit von 99,9999%. Natürlich kann die automatische Erkennung schiefgehen, wenn Sie z. B. mehrere Dateien mit demselben Namen und/oder demselben Inhalt haben.

98voto

Adam Nofsinger Punkte 3794

Von der offizielles GitFaq :

Git hat einen Befehl zum Umbenennen git mv aber das ist nur eine Bequemlichkeit. Die Wirkung ist nicht zu unterscheiden vom Entfernen der Datei und dem Hinzufügen einer anderen Datei mit anderem Namen und demselben Inhalt

19 Stimmen

Verlieren Sie also den Dateiverlauf? Ich hatte angenommen, dass beim Umbenennen der alte Verlauf für dieses Verzeichnis erhalten bleibt...

25 Stimmen

Nun, ja und nein. Lesen Sie den offiziellen GitFaq-Link oben über Umbenennungen, und lesen Sie dann Linus Torvalds lange E-Mail darüber, warum er die Vorstellung eines SCM-Tools, das Dateien verfolgt, nicht mag: permalink.gmane.org/gmane.comp.version-control.git/217

4 Stimmen

@WillHancock Ich habe jetzt etwas mehr mit Git gearbeitet und kann Ihnen eine genauere Antwort geben: Je nach Git-Client und seinen Optionen können Sie die Datei nach der Umbenennung zurückverfolgen, wenn die Datei intern nur so wenig geändert wurde, dass sie als umbenannt gilt. Wenn Sie die Datei jedoch zu sehr verändern UND umbenennen, wird Git dies nicht erkennen - es sagt gewissermaßen "Nein, du kannst das genauso gut als eine völlig andere Datei betrachten!

48voto

Sergey Orshanskiy Punkte 6434

Git versucht nur, für Sie zu erraten, was Sie zu tun versuchen. Es versucht alles, um eine ununterbrochene Geschichte zu bewahren. Natürlich ist es nicht perfekt. Deshalb git mv ermöglicht es Ihnen, Ihre Absicht klar zu formulieren und einige Fehler zu vermeiden.

Betrachten Sie dieses Beispiel. Wir beginnen mit einem leeren Projektarchiv,

git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
mv a c
mv b a
git status

Ergebnis:

# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   a
#   deleted:    b
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   c
no changes added to commit (use "git add" and/or "git commit -a")

Automatische Erkennung fehlgeschlagen :( Oder doch?

$ git add *
$ git commit -m "change"
$ git log c

commit 0c5425be1121c20cc45df04734398dfbac689c39
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:24:56 2013 -0400

    change

und dann

$ git log --follow c

Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:24:56 2013 -0400

    change

commit 50c2a4604a27be2a1f4b95399d5e0f96c3dbf70a
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:24:45 2013 -0400

    initial commit

Versuchen Sie nun stattdessen (vergessen Sie nicht, die .git Ordner beim Experimentieren):

git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
git mv a c
git status

So weit, so gut:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    a -> c

git mv b a
git status

Nun, niemand ist perfekt:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a
#   deleted:    b
#   new file:   c
#

Wirklich? Aber natürlich...

git add *
git commit -m "change"
git log c
git log --follow c

...und das Ergebnis ist dasselbe wie oben: nur --follow zeigt den gesamten Verlauf.


Seien Sie vorsichtig mit der Umbenennung, denn beide Optionen können immer noch seltsame Auswirkungen haben . Beispiel:

git init
echo "First" >a
git add a
git commit -m "initial a"
echo "Second" >b
git add b
git commit -m "initial b"

git mv a c
git commit -m "first move"
git mv b a
git commit -m "second move"

git log --follow a

commit 81b80f5690deec1864ebff294f875980216a059d
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:35:58 2013 -0400

    second move

commit f284fba9dc8455295b1abdaae9cc6ee941b66e7f
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:34:54 2013 -0400

    initial b

Kontrastieren Sie das mit:

git init
echo "First" >a
git add a
git commit -m "initial a"
echo "Second" >b
git add b
git commit -m "initial b"

git mv a c
git mv b a
git commit -m "both moves at the same time"

git log --follow a

Ergebnis:

commit 84bf29b01f32ea6b746857e0d8401654c4413ecd
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:37:13 2013 -0400

    both moves at the same time

commit ec0de3c5358758ffda462913f6e6294731400455
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:36:52 2013 -0400

    initial a

Ups... Jetzt geht die Geschichte zurück zu ursprünglich ein anstelle von ursprünglich b was falsch ist. Als wir also zwei Züge auf einmal machten, wurde Git verwirrt und verfolgte die Änderungen nicht richtig. In meinen Experimenten passierte übrigens dasselbe, wenn ich Dateien löschte/erstellte, anstatt git mv . Seien Sie vorsichtig; Sie wurden gewarnt...

7 Stimmen

+1 für die ausführliche Erklärung. Ich habe nach Problemen gesucht, die im Protokollverlauf auftreten können, wenn Dateien in Git verschoben werden, Ihre Antwort war wirklich interessant. Ich danke dir! Kennen Sie übrigens noch andere Fallstricke, die wir beim Verschieben von Dateien in Git vermeiden sollten? (oder irgendeine Referenz, auf die Sie verweisen könnten.... nicht viel Glück beim Googeln)

2 Stimmen

Nun, meine Beispiele sind pessimistisch. Wenn die Dateien leer sind, ist es viel schwieriger, die Änderungen richtig zu interpretieren. Ich denke, wenn Sie nach jeder Umbenennung ein Commit durchführen, sollte alles in Ordnung sein.

40voto

Colonel Panic Punkte 125419

Wie @Charles sagt, git mv ist eine Abkürzung.

Die eigentliche Frage lautet hier: "Andere Versionskontrollsysteme (z. B. Subversion und Perforce) behandeln Dateiumbenennungen besonders. Warum tut Git das nicht?"

Linus erklärt unter http://permalink.gmane.org/gmane.comp.version-control.git/217 mit charakteristischem Taktgefühl:

Bitte hören Sie mit diesem "Dateien verfolgen"-Mist auf. Git Spuren genau was zählt, nämlich "Sammlungen von Dateien". Nichts anderes ist relevant, ein Denken dass sie relevant ist, schränkt nur Ihr Weltbild ein. Beachten Sie, wie die Begriff CVS "annotate" immer unweigerlich dazu führt, dass die Leute die Verwendung es verwenden. Ich denke, es ist ein völlig nutzloses Stück Scheiße, und ich habe etwas beschrieben etwas, das meiner Meinung nach millionenfach nützlicher ist genau denn ich beschränke mein Denken nicht auf das falsche Modell der Welt.

19voto

duncan Punkte 2293

Es gibt einen Nischenfall, bei dem git mv ist nach wie vor sehr nützlich: wenn Sie die Groß-/Kleinschreibung eines Dateinamens in einem Dateisystem, das Groß-/Kleinschreibung nicht berücksichtigt, ändern möchten. Sowohl APFS (Mac) als auch NTFS (Windows) unterscheiden standardmäßig nicht zwischen Groß- und Kleinschreibung (behalten aber die Großschreibung bei).

greg.kindel erwähnt dies in einem Kommentar zu CB Baileys Antwort.

Angenommen, Sie arbeiten mit einem Mac und haben eine Datei Mytest.txt von git verwaltet. Sie möchten den Dateinamen ändern in MyTest.txt .

Sie könnten es versuchen:

$ mv Mytest.txt MyTest.txt
overwrite MyTest.txt? (y/n [n]) y
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Oh je. Git erkennt nicht an, dass die Datei geändert worden ist.

Sie könnte Sie können dieses Problem umgehen, indem Sie die Datei vollständig umbenennen und dann wieder zurückbenennen:

$ mv Mytest.txt temp.txt
$ git rm Mytest.txt
rm 'Mytest.txt'
$ mv temp.txt MyTest.txt
$ git add MyTest.txt 
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    Mytest.txt -> MyTest.txt

Hurra!

Oder Sie können sich die ganze Mühe sparen, indem Sie git mv :

$ git mv Mytest.txt MyTest.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    Mytest.txt -> MyTest.txt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X