source - ¿Cuál es el propósito de git-mv?
rename folder github (5)
Por lo que entiendo, Git no necesita realmente rastrear las operaciones de cambio de nombre / movimiento / copia de archivos , ¿cuál es el verdadero propósito de git mv ? La página del manual no es especialmente descriptiva ...
¿Es obsoleto? ¿Es un comando interno, no destinado a ser usado por usuarios regulares?
Como dice @Charles, git mv
es una taquigrafía.
La pregunta real aquí es "Otros sistemas de control de versión (por ejemplo, Subversion y Perforce) tratan los nombres de archivos de manera especial. ¿Por qué Git?"
Linus explica en permalink.gmane.org/gmane.comp.version-control.git/217 con tacto característico:
Por favor, deja esta "pista de archivos" basura. Git rastrea exactamente lo que importa, es decir, "colecciones de archivos". Nada más es relevante, e incluso pensar que es relevante solo limita tu visión del mundo. Observe cómo la noción de "anotación" de CVS siempre termina limitando inevitablemente la forma en que la gente lo usa. Creo que es un pedazo de mierda totalmente inútil, y he descrito algo que creo que es un millón de veces más útil, y todo se cayó exactamente porque no estoy limitando mi pensamiento al modelo equivocado del mundo.
Desde el GitFaq oficial :
Git tiene un comando de cambio de nombre
git mv
, pero eso es solo una conveniencia. El efecto es indistinguible de eliminar el archivo y agregar otro con un nombre diferente y el mismo contenido
Git está tratando de adivinar qué estás tratando de hacer. Se está haciendo todo lo posible para preservar la historia ininterrumpida. Por supuesto, no es perfecto. Entonces git mv
te permite ser explícito con tu intención y evitar algunos errores.
Considera este ejemplo. Comenzando con un repositorio vacío,
git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
mv a c
mv b a
git status
Resultado:
# 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")
Autodetección fallida :( ¿O lo hizo?
$ 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
y entonces
$ 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
Ahora intente en su lugar (recuerde eliminar la carpeta .git
al experimentar):
git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
git mv a c
git status
Hasta ahora tan bueno:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: a -> c
git mv b a
git status
Ahora, nadie es perfecto:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a
# deleted: b
# new file: c
#
De Verdad? Pero por supuesto...
git add *
git commit -m "change"
git log c
git log --follow c
... y el resultado es el mismo que el de arriba: solo --follow
muestra el historial completo.
Ahora, tenga cuidado con el cambio de nombre, ya que cualquiera de las dos opciones puede producir efectos extraños . Ejemplo:
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
Contrastarlo con:
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
Resultado:
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 ... Ahora la historia está volviendo a la inicial a en lugar de la inicial b , lo cual está mal. Entonces, cuando hicimos dos movimientos a la vez, Git se confundió y no siguió los cambios correctamente. Por cierto, en mis experimentos sucedió lo mismo cuando eliminé / creé archivos en lugar de usar git mv
. Proceda con cuidado; has sido advertido...
Hay otro uso que tengo para git mv
no mencionado anteriormente.
Desde el descubrimiento de git add -p
(modo de parche de git add; consulte http://git-scm.com/docs/git-add ), me gusta usarlo para revisar los cambios a medida que los agrego al índice. De este modo, mi flujo de trabajo se convierte en (1) trabajo en código, (2) revisión y adición al índice, (3) confirmación.
¿Cómo encaja git mv
? Si mueve un archivo directamente y luego usa git rm
y git add
, todos los cambios se agregan al índice, y usar git diff para ver los cambios es menos fácil (antes de confirmar). Sin embargo, al usar git mv
, se agrega la nueva ruta al índice, pero no los cambios realizados en el archivo, lo que permite que git diff
y git add -p
funcionen como siempre.
git mv oldname newname
es solo una taquigrafía para:
mv oldname newname
git add newname
git rm oldname
es decir, actualiza el índice para las rutas antiguas y nuevas automáticamente.