3. September 2013

Dateien umbenennen

git verwaltet Umbenennungen von Dateien und Ordnern nicht explizit. Stattdessen werden Umbenennungen automatisch erkannt. Jeder Commit ist ein eigenständiger Snapshot der Dateien - wird eine Datei umbenannt, liegt sie in dem einen Commit an der einen Stelle, in dem anderen Commit an der anderen Stelle; im Log wird dies als Löschung und Neu-Hinzufügen angezeigt.

Das Kommando git mv ist lediglich eine Abkürzung, um eine Datei im Working Tree und im Index in einem Schritt umzubenennen:

$ git mv index.html start.html

$ git status

# Changes to be committed:
#
#    renamed:    index.html -> start.html

Dies ist identisch mit:

$ mv index.html start.html

$ git add start.html
$ git rm index.html

$ git status

# On branch master
#
#    renamed:    index.html -> start.html

Das heißt, Umbenennungen müssen nicht explizit mit git mv ausgeführt werden. Die zugrundeliegende Heuristik erkennt eine Umbenennung sogar wenn die Inhalte nicht exakt identisch sind (standardmäßig bis zu einer Ähnlichkeit von 50%):

$ git commit -m "rename"
 1 file changed, 1 insertion(+), 1 deletion(-)
 rename src/{index.html => start.html} (81%)

Da git nur Dateien und Dateiinhalte verwaltet, gilt das gleiche für Verschiebungen und Umbenennungen von Ordnern:

$ git mv src/ project1/src
$ git status

# Changes to be committed:
#
#    renamed:    src/start.html -> project1/src/start.html

Dies hat den Vorteil, das für Umbenennungen und Refactorings beliebige Tools verwendet werden können und keine Umbenennungen vergessen werden können.

Anzeige von Umbenennungen in git log

Aus Performancegründen werden Umbenennungen im Log standardmäßig nicht angezeigt. Die Erkennung wird mit der Option -M aktiviert:

$ git log -M -p
$ git show -M

Dieses Verhalten lässt sich standardmäßig aktivieren mit:

$ git config --global diff.renames true

Ebenso werden bei Logausgaben, die bestimmte Dateien betreffen, Umbenennungen nur verfolgt, wenn dies mit --follow explizit angegeben wird:

$ git log project1/src/start.html
d123a52 - folder moved

$ git log --follow project1/src/start.html
d123a52 - folder moved
024a232 - rename
d583416 - created index.html

Umbenennungen beim Merge

Die automatische Erkennung von umbenannten Dateien wird spätestens beim Merge sehr nützlich, da man Umbenennungen nicht versehentlich vergessen kann und dann später beim Merge unnötigen Aufwand bekommt, weil die Dateien nicht zugeordnet werden können.

Wurde im obigen Beispiel z.B. ein Branch von dem Stand mit dem ursprünglichen Dateinamen abgeleitet und hier ebenfalls Änderungen an der Datei vorgenommen, wird Git beim Merge automatisch die Heuristik zur Erkennung von Umbenennungen anwenden und die Änderung entsprechend mergen:

$ git log master
d123a52 - folder moved
024a232 - rename
d583416 - created index.html

$ git log old_change
e279ff7 - updated index.html
d583416 - created index.html

$ git merge old_change
Auto-merging project1/src/start.html
Merge made by the 'recursive' strategy.
 project1/src/start.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)