2017-09-15 2 views
1

Letzten Monat fing ich an, zu einem GitHub-Repository beizutragen, indem ich das entsprechende Repo gab, einen Feature-Zweig erstellte und dann eine Pull-Anfrage abgab. Während ich diesen Prozess für ein paar Tage wiederholte, stieß ich auf ein seltsames Problem beim Umbenennen von Dateien mit dem vorinstallierten Linux-Befehl mv und auch mit dem Git-Befehl git mv.Odd `git mv` Verhalten

Das eigentliche Problem ist, dass je nachdem, wann Sie bewegen/eine Datei mit git mv umbenennen, wenn Sie git add es und zu welchem ​​Zeitpunkt Sie die umbenannte Datei bearbeiten, Sie entweder:

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

     renamed: somethingelse -> something 

Oder diese:

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

     new file: something 
     deleted: somethingelse 

Um dies zu demonstrieren, habe ich eine schriftliche test:

#!/bin/bash 

# To my knowledge, this “problem” only occurs with new files in a Git repo 
printf "COMMAND: mkdir -v gitrepo\n\n" 
mkdir -v gitrepo 

printf "\nCOMMAND: cd gitrepo\n\n" 
cd gitrepo 

printf "\nCOMMAND: git init\n\n" 
git init 

printf "\nCOMMAND: git status\n\n" 
git status 

printf "\nCOMMAND: touch something\n\n" 
touch something 

printf "\nCOMMAND: git status\n\n" 
git status 

printf "\nCOMMAND: git add something\n\n" 
git add something 

printf "\nCOMMAND: git status\n\n" 
git status 

printf '\nCOMMAND: git commit -m "Added something"\n\n' 
git commit -m "Added something" 

printf "\nCOMMAND: git status\n\n" 
git status 

printf "\nCOMMAND: git mv something somethingelse\n\n" 
git mv something somethingelse 

printf "\nCOMMAND: git status\n\n" 
git status 

# Type in the following on line 1: First line of code 
printf "\nCOMMAND: vim somethingelse\n\n" 
vim somethingelse 

printf "\nCOMMAND: git status\n\n" 
git status 

printf "\nCOMMAND: git add somethingelse\n\n" 
git add somethingelse 

printf "\nCOMMAND: git status\n\n" 
git status 

printf '\nCOMMAND: git commit -m "Renamed something to somethingelse and edited somethingelse"\n\n' 
git commit -m "Renamed something to somethingelse and edited somethingelse" 

printf "\nCOMMAND: git status\n\n" 
git status 

printf "\nCOMMAND: git mv somethingelse something\n\n" 
git mv somethingelse something 

printf "\nCOMMAND: git status\n\n" 
git status 

# If you add something to the first line, the rename will not be detected by Git 
# However, if you instead create 2 newlines and fill line 3 with new code, 
# the rename gets detected for whatever reason 
printf "\nCOMMAND: vim something\n\n" 
vim something 

printf "\nCOMMAND: git status\n\n" 
git status 

printf "\nCOMMAND: git add something\n\n" 
git add something 

printf "\nCOMMAND: git status\n\n" 
git status 

printf '\nCOMMAND: git commit -m "Renamed somethingelse to something and edited something"\n\n' 
git commit -m "Renamed somethingelse to something and edited something" 

printf "\nCOMMAND: git status\n\n" 
git status 

cd .. && rm -fr gitrepo && printf "\nREMOVED gitrepo folder\n" 
printf "\nDONE.\n" 

Aus irgendeinem Grund betrifft dies hauptsächlich "neue Dateien" und nicht die, die bereits in einem Repository vorhanden sind. Wenn Sie beispielsweise meine Verzweigung Spoon-Knife repository mit git clone https://github.com/christianheinrichs/Spoon-Knife.git klonen und dann den Arbeitsablauf des verknüpften Testskripts anwenden, werden Sie feststellen, dass Sie die Datei README.md in den meisten Fällen in README umbenennen und bearbeiten können Es wird immer noch als Umbenennung anstelle einer neuen Datei/gelöschten Teilung gezählt.

Obwohl ich die neue Datei/gelöscht Verhalten auf dem geklonten Löffel-Messer-Gabel-Repo reproduzieren konnte, bin ich nicht genau sicher, wie ich das tat und glaube mir, wenn ich sage, dass ich versucht habe, es herauszufinden.

Also was genau hier los ist, verstehe ich nicht?

See: https://gist.github.com/christianheinrichs/e50bfdd5eec70a606fa6ce4a88c5951b#file-git_mv-test-sh-L65

Antwort

4

git nicht hält eine Fahne sagen "diese newname Datei zunächst oldname Datei aufgerufen wurde":

git mv oldname newname 

# is exactly equivalent to : 

mv oldname newname 
git rm oldname 
git add newname 

Wenn der Status einer Datei anzuzeigen, git versucht, wenn es zu erraten war ein rename oder ein delete + add durch den Inhalt der Dateien vergleichen, und sehen, wie sie ähnlich sind.

Also: Wenn Sie durch git mv eine Datei starten, und dann die Datei bearbeiten, je nachdem, wie viel die Datei geändert wird, git der Lage sein kann oder auch nicht zu sehen, dass sie alle mit einem mv gestartet.

Siehe auch die Antwort auf diese Frage: How does Git know that file was renamed?

+1

Beachten Sie auch, dass, wenn Sie laufen 'git diff' Sie aktivieren oder deaktivieren können Erkennung umbenennen, und stellen Sie die„Ähnlichkeitsschwelle“-Nummer. Wenn 'git status'' git diff' für Sie ausführt, wird in diesem Fall der Ähnlichkeitsschwellenwert auf 50% gesetzt: Die Erkennung von Umbenennungen ist immer aktiviert und der Schwellenwert ist festgelegt. – torek

+0

@torek Ich nehme an, du redest über 'git diff -M [], --find-renames [= ]'? Das ist ein nettes Feature, von dem ich nichts wusste und das Problem in meiner zweiten Frage teilweise erklären könnte. –

+0

@LeGEC Vielen Dank für Ihre Antwort. Aber bevor ich es akzeptiere, kannst du das Git-Verhalten in der zweiten Frage erklären, die ich angehängt habe? 'Also, warum erkennt Git das Umbenennen nicht, wenn Sie etwas zur ersten Zeile hinzufügen, aber wenn Sie statt dessen 2 Zeilenumbrüche erstellen und Zeile 3 mit neuem Code füllen?' –