tag - ¿Cómo hacer que git mark un archivo eliminado y un nuevo como un archivo mover?
git push tag (14)
He movido un archivo manualmente y luego lo he modificado. Según Git, es un archivo nuevo y un archivo eliminado. ¿Hay alguna manera de obligar a Git a tratarla como un movimiento de archivo?
Aquí hay una solución rápida y sucia para uno, o algunos, archivos renombrados y modificados que no están comprometidos.
Digamos que el archivo se llamó foo
y ahora se llama bar
:
Cambiar el nombre de la
bar
a un nombre temporal:mv bar side
Salida
foo
:git checkout HEAD foo
Cambie el nombre de
foo
abar
con Git:git mv foo bar
Ahora cambie el nombre de su archivo temporal a la
bar
.mv side bar
Este último paso es lo que hace que el contenido modificado vuelva al archivo.
Si bien esto puede funcionar, si el archivo movido es demasiado diferente en contenido del git original, considerará que es más eficiente decidir que se trata de un nuevo objeto. Déjame demostrar:
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: work.js
$ git add README.md work.js # why are the changes unstaged, let''s add them.
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
deleted: README
new file: README.md
modified: work.js
$ git stash # what? let''s go back a bit
Saved working directory and index state WIP on dir: f7a8685 update
HEAD is now at f7a8685 update
$ git status
On branch workit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.idea/
nothing added to commit but untracked files present (use "git add" to track)
$ git stash pop
Removing README
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
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)
deleted: README
modified: work.js
Dropped refs/stash@{0} (1ebca3b02e454a400b9fb834ed473c912a00cd2f)
$ git add work.js
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
modified: work.js
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)
deleted: README
$ git add README # hang on, I want it removed
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
deleted: README
new file: README.md
modified: work.js
$ mv README.md Rmd # Still? Try the answer I found.
$ git checkout README
error: pathspec ''README'' did not match any file(s) known to git.
$ git checkout HEAD README # Ok the answer needed fixing.
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
modified: work.js
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)
deleted: README.md
modified: work.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
Rmd
$ git mv README README.md
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
modified: work.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: work.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
Rmd
$ mv Rmd README.md
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
modified: work.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: work.js
$ # actually that''s half of what I wanted; /
# and the js being modified twice? Git prefers it in this case.
Cuando edito, renombro y muevo un archivo al mismo tiempo, ninguna de estas soluciones funciona. La solución es hacerlo en dos confirmaciones (editar y renombrar / mover por separado) y luego fixup
la segunda confirmación mediante git rebase -i
para tenerla en una confirmación.
Git detectará automáticamente el movimiento / cambio de nombre si su modificación no es demasiado grave. Solo git add
el nuevo archivo, y git rm
el archivo antiguo. git status
mostrará si se ha cambiado el nombre.
Además, para desplazarse por directorios, es posible que deba:
- cd a la parte superior de esa estructura de directorios.
- Ejecutar
git add -A .
- Ejecute
git status
para verificar que el "nuevo archivo" ahora es un archivo "renombrado"
Si el estado de git aún muestra "nuevo archivo" y no "renombrado", debe seguir el consejo de Hank Gay y hacer el movimiento y modificarlo en dos confirmaciones separadas.
Haz el movimiento y modifica en confirmaciones separadas.
La forma en que entiendo esta pregunta es "Cómo hacer que git reconozca la eliminación de un archivo antiguo y la creación de un nuevo archivo como un movimiento de archivo".
Sí en el directorio de trabajo, una vez que elimines un archivo antiguo e insertas un archivo antiguo, git status
dirá " deleted: old_file
" y " Untracked files: ... new_file
"
Pero en el índice / nivel de preparación, una vez que agregue y elimine un archivo con git, se reconocerá como un movimiento de archivo. Para hacerlo, suponiendo que ha hecho la eliminación y creación utilizando su sistema operativo, dé los siguientes comandos:
git add new_file
git rm old_file
Si el contenido del archivo es similar al 50% o más, ejecutar el comando git status
debería proporcionarle:
renamed: old_file -> new_file
Para mí, funcionó para guardar todos los cambios antes de la confirmación y volver a desplegarlos. Esto hizo que git volviera a analizar los archivos agregados / eliminados y los marcó correctamente como movidos.
Probablemente hay una mejor forma de "línea de comando" para hacer esto, y sé que esto es un truco, pero nunca he podido encontrar una buena solución.
Uso de TortoiseGIT: si tiene una confirmación GIT en la que algunas operaciones de movimiento de archivos se muestran como una carga de agregados / eliminaciones en lugar de cambios de nombre, aunque los archivos solo tengan pequeños cambios, haga lo siguiente:
- Comprueba lo que has hecho localmente
- Compruebe en un mini cambio de una línea en un segundo compromiso
- Ir al registro de GIT en git tortuga
- Seleccione las dos confirmaciones, haga clic con el botón derecho y seleccione "fusionar en una confirmación"
La nueva confirmación ahora mostrará correctamente los nombres de los archivos ... lo que ayudará a mantener el historial de archivos adecuado.
Recientemente tuve este problema, al mover (pero no modificar) algunos archivos.
El problema es que Git cambió algunos finales de línea cuando moví los archivos, y luego no pudo decir que los archivos eran los mismos.
El uso de git mv
solucionó el problema, pero solo funciona en archivos / directorios individuales, y tenía muchos archivos en la raíz del repositorio que hacer.
Una forma de arreglar esto sería con algo de magia de bash / batch.
Otra forma es la siguiente
- Mueve los archivos y
git commit
. Esto actualiza los finales de línea. - Mueva los archivos a su ubicación original, ahora que tienen los nuevos finales de línea, y
git commit --amend
- Mueve los archivos de nuevo y
git commit --amend
. No hay cambios en los finales de línea esta vez, así que Git está contento.
Si está hablando de que el git status
no muestra los nombres, intente git commit --dry-run -a
lugar
Si está utilizando TortoiseGit, es importante tener en cuenta que la detección automática de cambio de nombre de Git se produce durante la confirmación, pero el software no siempre muestra el hecho de que sucederá de antemano. Había movido dos archivos a un directorio diferente y realicé algunas ediciones leves. Utilizo TortoiseGit como mi herramienta de confirmación y la lista de Cambios realizados muestra los archivos que se eliminan y agregan, no se mueven. Ejecutar el estado de git desde la línea de comandos mostró una situación similar. Sin embargo, después de confirmar los archivos, aparecieron como renombrados en el registro. Entonces, la respuesta a tu pregunta es que, siempre y cuando no hayas hecho nada drástico, Git debería cambiar el nombre automáticamente.
Editar: Aparentemente, si agrega los nuevos archivos y luego hace un estado de git desde la línea de comandos, el cambio de nombre debería aparecer antes de cometer.
Edición 2: Además, en TortoiseGit, agregue los nuevos archivos en el cuadro de diálogo de confirmación pero no los confirme. Luego, si ingresa al comando Mostrar registro y mira el directorio de trabajo, verá si Git ha detectado el cambio de nombre antes de comprometerse.
La misma pregunta se planteó aquí: https://tortoisegit.org/issue/1389 y se ha registrado como un error para solucionar aquí: https://tortoisegit.org/issue/1440 Resulta que es un problema de visualización con el compromiso de TortoiseGit diálogo y también existe algo en el estado de git si no ha agregado los nuevos archivos.
Todo es una cosa perceptiva. Git es generalmente bastante bueno para reconocer movimientos, porque GIT es un rastreador de contenido
Todo lo que realmente depende es cómo su "estadística" lo muestra. La única diferencia aquí es la bandera -M.
registro de git --stat -M
commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date: Fri Jan 9 22:13:51 2009 +1300
Category Restructure
lib/Gentoo/Repository.pm | 10 +++++-----
lib/Gentoo/{ => Repository}/Base.pm | 2 +-
lib/Gentoo/{ => Repository}/Category.pm | 12 ++++++------
lib/Gentoo/{ => Repository}/Package.pm | 10 +++++-----
lib/Gentoo/{ => Repository}/Types.pm | 10 +++++-----
5 files changed, 22 insertions(+), 22 deletions(-)
git log --stat
commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date: Fri Jan 9 22:13:51 2009 +1300
Category Restructure
lib/Gentoo/Base.pm | 36 ------------------------
lib/Gentoo/Category.pm | 51 ----------------------------------
lib/Gentoo/Package.pm | 41 ---------------------------
lib/Gentoo/Repository.pm | 10 +++---
lib/Gentoo/Repository/Base.pm | 36 ++++++++++++++++++++++++
lib/Gentoo/Repository/Category.pm | 51 ++++++++++++++++++++++++++++++++++
lib/Gentoo/Repository/Package.pm | 41 +++++++++++++++++++++++++++
lib/Gentoo/Repository/Types.pm | 55 +++++++++++++++++++++++++++++++++++++
lib/Gentoo/Types.pm | 55 -------------------------------------
9 files changed, 188 insertions(+), 188 deletions(-)
git registro de ayuda
-M
Detect renames.
-C
Detect copies as well as renames. See also --find-copies-harder.
Use el comando git mv
para mover los archivos, en lugar de los comandos de movimiento del sistema operativo: https://git-scm.com/docs/git-mv
Tenga en cuenta que el comando git mv
solo existe en las versiones Git 1.8.5 y superiores. Así que es posible que tengas que actualizar tu Git para usar este comando.
git diff -M
o git log -M
deberían detectar automáticamente tales cambios como un cambio de nombre con cambios menores siempre que lo sean. Si sus cambios menores no son menores, puede reducir la similitud que tiene, por ejemplo
$ git log -M20 -p --stat
para reducirlo del valor predeterminado del 50% al 20%.
¡O puedes intentar la respuesta a esta pregunta here con here ! Para citarlo de nuevo:
Primero, cancele su agregado en escena para el archivo movido manualmente:
$ git reset path/to/newfile
$ mv path/to/newfile path/to/oldfile
Luego, usa Git para mover el archivo:
$ git mv path/to/oldfile path/to/newfile
Por supuesto, si ya ha realizado el movimiento manual, es posible que desee restablecer la revisión antes del movimiento en su lugar, y luego simplemente git mv desde allí.