sobreescribir - git push example
¿Cómo puedo forzar "git pull" para sobrescribir archivos locales? (30)
¿Cómo fuerzo una sobrescritura de archivos locales en un git pull
?
El escenario es el siguiente:
- Un miembro del equipo está modificando las plantillas para un sitio web en el que estamos trabajando.
- Están agregando algunas imágenes al directorio de imágenes (pero se olvida de agregarlas bajo el control de código fuente)
- Me están enviando las imágenes por correo, más tarde, a mí.
- Estoy agregando las imágenes bajo el control de origen y presionándolas a GitHub junto con otros cambios
- No pueden obtener actualizaciones de GitHub porque Git no quiere sobrescribir sus archivos.
Este es el error que estoy recibiendo:
error: Untracked working tree file ''public/images/icon.gif'' would be overwritten by merge
¿Cómo obligo a Git a que los sobrescriba? La persona es un diseñador: generalmente resuelvo todos los conflictos a mano, por lo que el servidor tiene la versión más reciente que solo necesita actualizar en su computadora.
Importante: Si tienes algún cambio local, se perderán. Con o sin la opción --hard
, se --hard
los compromisos locales que no hayan sido empujados. [*]
Si tiene algún archivo que Git no rastrea (por ejemplo, contenido de usuario cargado), estos archivos no se verán afectados.
Creo que esta es la manera correcta:
git fetch --all
Entonces, tienes dos opciones:
git reset --hard origin/master
O si estás en alguna otra rama:
git reset --hard origin/<branch_name>
Explicación:
git fetch
descarga lo último desde el control remoto sin intentar fusionar o volver a generar nada.
Luego, el git reset
restablece la rama maestra a lo que acabas de recuperar. La opción --hard
cambia todos los archivos en su árbol de trabajo para que coincidan con los archivos en origin/master
Mantener los compromisos locales actuales.
[*] : Vale la pena señalar que es posible mantener las confirmaciones locales actuales creando una rama desde el master
antes de reiniciar:
git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard origin/master
Después de esto, todas las confirmaciones antiguas se mantendrán en las confirmaciones new-branch-to-save-current-commits
.
Cambios no comprometidos
Sin embargo, los cambios no comprometidos (incluso en etapas) se perderán. Asegúrate de guardar y cometer todo lo que necesites. Para eso puedes ejecutar lo siguiente:
git stash
Y luego volver a aplicar estos cambios no comprometidos:
git stash pop
Prima:
Al hablar de extracción / recuperación / fusión en las respuestas anteriores, me gustaría compartir un truco interesante y productivo,
git pull --rebase
Este comando anterior es el comando más útil en mi vida de Git que ahorró mucho tiempo.
Antes de enviar su nuevo compromiso al servidor, pruebe este comando, se sincronizarán automáticamente los últimos cambios del servidor (con fetch + merge) y colocará su compromiso en la parte superior del registro de Git. No hay necesidad de preocuparse por la extracción / fusión manual.
Encuentra detalles en ¿Qué hace "git pull --rebase"? .
A pesar de la pregunta original, las respuestas principales pueden causar problemas a las personas que tienen un problema similar, pero que no quieren perder sus archivos locales. Por ejemplo, vea los comentarios de Al-Punk y crizCraig.
La siguiente versión confirma sus cambios locales en una rama temporal ( tmp
), verifica la rama original (que asumo que es la master
) y combina las actualizaciones. Podría hacer esto con el stash
, pero me parece que generalmente es más fácil simplemente usar el enfoque de ramificación / combinación.
git checkout -b tmp
git add *; git commit -am "my temporary files"
git checkout master
git fetch origin master
git merge -s recursive -X theirs origin master
donde asumimos que el otro repositorio es origin master
.
Acabo de resolver esto yo mismo por:
git checkout -b tmp # "tmp" or pick a better name for your local changes branch
git add -A
git commit -m ''tmp''
git pull
git checkout master # Or whatever branch you were on originally
git pull
git diff tmp
donde el último comando proporciona una lista de los cambios locales. Siga modificando la rama "tmp" hasta que sea aceptable y luego vuelva a combinar en el maestro con:
git checkout master && git merge tmp
Para la próxima vez, probablemente pueda manejar esto de una manera más limpia buscando "rama de escondite de git", aunque es probable que el alijo le cause problemas en los primeros intentos, así que primero experimente en un proyecto no crítico ...
Al igual que Hedgehog, creo que las respuestas son terribles. Pero aunque la respuesta de Hedgehog podría ser mejor, no creo que sea tan elegante como podría ser. La forma en que encontré que hacer esto es usando "fetch" y "fusionar" con una estrategia definida. Lo que debería permitir que los cambios locales se conserven siempre que no sean uno de los archivos con los que intenta forzar una sobrescritura.
Primero haz un commit de tus cambios.
git add *
git commit -a -m "local file server commit message"
Luego recupera los cambios y sobrescribe si hay un conflicto
git fetch origin master
git merge -s recursive -X theirs origin/master
"-X" es un nombre de opción, y "suyo" es el valor de esa opción. Está eligiendo usar "sus" cambios, en lugar de "sus" cambios si hay un conflicto.
Basándome en mis experiencias similares, la solución ofrecida por Strahinja Kustudic es, con mucho, la mejor. Como otros lo han señalado, simplemente hacer un restablecimiento completo eliminará todos los archivos sin seguimiento que podrían incluir muchas cosas que no desea eliminar, como los archivos de configuración. Lo que es más seguro es eliminar solo los archivos que están a punto de agregarse y, para el caso, es probable que también desee revisar los archivos modificados localmente que estén a punto de actualizarse.
Teniendo esto en cuenta, actualicé el script de Kustudic para hacer precisamente eso. También arreglé un error tipográfico (falta) en el original.
#/bin/sh
# Fetch the newest code
git fetch
# Delete all files which are being added,
# so there are no conflicts with untracked files
for file in `git diff HEAD..origin/master --name-status | awk ''/^A/ {print $2}''`
do
echo "Deleting untracked file $file..."
rm -vf "$file"
done
# Checkout all files which have been locally modified
for file in `git diff HEAD..origin/master --name-status | awk ''/^M/ {print $2}''`
do
echo "Checking out modified file $file..."
git checkout $file
done
# Finally merge all the changes (you could use merge here as well)
git pull
Conozco un método mucho más fácil y menos doloroso:
$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp
¡Eso es!
Creo que hay dos posibles causas de conflicto, que deben resolverse por separado, y por lo que puedo decir, ninguna de las respuestas anteriores trata de ambas:
Los archivos locales que no están rastreados deben eliminarse, ya sea de forma manual (más segura) o como se sugiere en otras respuestas, por
git clean -f -d
Las confirmaciones locales que no están en la rama remota también deben eliminarse. OMI, la forma más fácil de lograr esto es con:
git reset --hard origin/master
(reemplace ''master'' por cualquier rama en la que esté trabajando, y ejecute primero ungit fetch origin
)
El problema con todas estas soluciones es que todas son demasiado complejas, o, un problema aún mayor, es que eliminan todos los archivos sin seguimiento del servidor web, lo que no queremos, ya que siempre hay archivos de configuración necesarios que están en El servidor y no en el repositorio Git.
Aquí está la solución más limpia que estamos usando:
# Fetch the newest code
git fetch
# Delete all files which are being added, so there
# are no conflicts with untracked files
for file in `git diff HEAD..origin/master --name-status | awk ''/^A/ {print $2}''`
do
rm -f -- "$file"
done
# Checkout all files which were locally modified
for file in `git diff --name-status | awk ''/^[CDMRTUX]/ {print $2}''`
do
git checkout -- "$file"
done
# Finally pull all the changes
# (you could merge as well e.g. ''merge origin/master'')
git pull
El primer comando obtiene los datos más recientes.
El segundo comando verifica si hay algún archivo que se esté agregando al repositorio y elimina esos archivos no rastreados del repositorio local, lo que podría causar conflictos.
El tercer comando extrae todos los archivos que se modificaron localmente.
Finalmente, hacemos un esfuerzo para actualizar a la versión más reciente, pero esta vez sin ningún conflicto, ya que los archivos sin seguimiento que están en el repositorio ya no existen y todos los archivos modificados localmente ya son los mismos que en el repositorio.
En lugar de fusionarse con git pull
, intente esto:
git fetch --all
seguido por:
git reset --hard origin/master
.
En lugar de hacer:
git fetch --all
git reset --hard origin/master
Aconsejaría hacer lo siguiente:
git fetch origin master
git reset --hard origin/master
¿No es necesario recuperar todos los controles remotos y las ramas si va a restablecer la rama de origen / maestra?
En primer lugar, pruebe el modo estándar:
git reset HEAD --hard # Remove all not committed changes
Si lo anterior no ayuda y no le importan sus archivos / directorios sin seguimiento (haga la copia de seguridad primero por si acaso), intente los siguientes pasos simples:
cd your_git_repo # where ''your_git_repo'' is your git repository folder
rm -rfv * # WARNING: only run inside your git repository!
git pull # pull the sources again
Esto RETIRARÁ todos los archivos git (excempt .git/
dir, donde tiene todos los confirmaciones) y tire de nuevo.
¿Por qué git reset HEAD --hard
podría fallar en algunos casos?
Reglas personalizadas en el
.gitattributes file
Tener una regla
eol=lf
en .gitattributes podría hacer que git modifique algunos cambios de archivo al convertir los finales de línea CRLF en LF en algunos archivos de texto.Si ese es el caso, debes confirmar estos cambios CRLF / LF (
git config core.autcrlf false
en elgit status
), o prueba:git config core.autcrlf false
para ignorarlos temporalmente.Incompatibilidad del sistema de archivos
Cuando estás usando un sistema de archivos que no admite atributos de permiso. En el ejemplo, tiene dos repositorios, uno en Linux / Mac (
ext3
/hfs+
) y otro en el sistema de archivos basado en FAT32 / NTFS.Como puede observar, hay dos tipos diferentes de sistemas de archivos, por lo que el que no admite los permisos de Unix básicamente no puede restablecer los permisos de archivos en el sistema que no admite ese tipo de permisos, así que no importa cómo lo
--hard
. Intenta, git siempre detecta algunos "cambios".
Estos cuatro comandos funcionan para mí.
git reset --hard HEAD
git checkout origin/master
git branch -D master
git checkout -b master
Para comprobar / jalar después de ejecutar estos comandos.
git pull origin master
Intenté mucho, pero finalmente tuve éxito con estos comandos.
Leí todas las respuestas pero estaba buscando un solo comando para hacer esto. Aquí esta lo que hice. Añadido un alias de git a .gitconfig
[alias]
fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"
Ejecute su comando como
git fp origin master
equivalente a
git fetch origin master
git reset --hard origin/master
Lo único que me funcionó fue:
git reset --hard HEAD~5
Esto te hará retroceder cinco compromisos y luego con
git pull
Encontré que al mirar hacia arriba, cómo deshacer una fusión de Git .
Parece que la mayoría de las respuestas aquí están enfocadas en la rama master
; sin embargo, hay ocasiones en las que estoy trabajando en la misma rama de función en dos lugares diferentes y quiero que una rebase en una se refleje en la otra sin tener que saltar mucho en los aros.
Basándome en una combinación de la respuesta de RNA y la respuesta de torek a una pregunta similar , se me ocurrió una que funciona de manera espléndida:
git fetch
git reset --hard @{u}
Ejecuta esto desde una rama y solo restablecerá tu rama local a la versión ascendente.
Esto también se puede poner muy bien en un alias de git forcepull
( git forcepull
):
git config alias.forcepull "!git fetch ; git reset --hard @{u}"
O, en su archivo .gitconfig
:
[alias]
forcepull = "!git fetch ; git reset --hard @{u}"
¡Disfrutar!
Parece que la mejor manera es hacer primero:
git clean
Para eliminar todos los archivos sin seguimiento y luego continuar con la git pull
habitual de git pull
...
Prueba esto:
git reset --hard HEAD
git pull
Debería hacer lo que quieras.
Puede encontrar este comando útil para desechar cambios locales:
git checkout <your-branch> -f
Y luego haga una limpieza (elimina los archivos sin seguimiento del árbol de trabajo):
git clean -f
Si desea eliminar directorios sin seguimiento además de los archivos sin seguimiento:
git clean -fd
Requisitos:
- Rastrea los cambios locales para que nadie aquí los pierda.
- Haga que el repositorio local coincida con el repositorio de origen remoto.
Solución:
- Guarda los cambios locales.
Recupera con una limpieza de archivos y directorios ignorando .gitignore y restableciendo por hardware a origen .
git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master
Restablezca el índice y la cabecera a origin/master
, pero no reinicie el árbol de trabajo:
git reset origin/master
Resumí otras respuestas. Puedes ejecutar git pull
sin errores:
git fetch --all
git reset --hard origin/master
git reset --hard HEAD
git clean -f -d
git pull
Advertencia : este script es muy poderoso, por lo que podría perder sus cambios.
Solo haz
git fetch origin branchname
git checkout -f origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge origin/branchname
Por lo tanto, evita todos los efectos secundarios no deseados, como eliminar archivos o directorios que desea conservar, etc.
Tengo una situación extraña que no funciona ni git clean
ni git reset
. Tengo que eliminar el archivo conflictivo del git index
usando el siguiente script en cada archivo sin seguimiento:
git rm [file]
Entonces puedo tirar bien.
Tuve el mismo problema y por alguna razón, incluso un git clean -f -d
no lo haría. He aquí por qué: por algún motivo, si Git ignora su archivo (a través de una entrada de .gitignore, supongo), todavía le preocupa sobrescribir esto con una extracción posterior, pero una limpieza no lo eliminará, a menos que agregue -x
.
Tuve un problema similar. Tuve que hacer esto:
git reset --hard HEAD
git clean -f
git pull
Una forma más fácil sería:
git checkout --theirs /path/to/file.extension
git pull origin master
Esto anulará su archivo local con el archivo en git
Yo tuve el mismo problema. Nadie me dio esta solución, pero funcionó para mí.
Lo resolví por:
- Eliminando todos los archivos. Deja solo el directorio .git.
-
git reset --hard HEAD
-
git pull
-
git push
Ahora funciona.
Algunas respuestas parecen ser terribles. Terrible en el sentido de lo que le sucedió a @Lauri siguiendo la sugerencia de David Avsajanishvili.
Más bien (git> v1.7.6):
git stash --include-untracked
git pull
Más tarde podrás limpiar la historia del alijo.
Manualmente, uno por uno:
$ git stash list
stash@{0}: WIP on <branch>: ...
stash@{1}: WIP on <branch>: ...
$ git stash drop stash@{0}
$ git stash drop stash@{1}
Brutalmente, todos a la vez:
$ git stash clear
Por supuesto, si quieres volver a lo que escondiste:
$ git stash list
...
$ git stash apply stash@{5}
ADVERTENCIA: git clean
elimina todos los archivos / directorios sin seguimiento y no se puede deshacer.
A veces simplemente clean -f
no ayuda. En caso de que tenga DIRECTORIOS sin seguimiento, la opción -d también es necesaria:
# WARNING: this can''t be undone!
git reset --hard HEAD
git clean -f -d
git pull
ADVERTENCIA: git clean
elimina todos los archivos / directorios sin seguimiento y no se puede deshacer.
Considera usar primero la bandera -n
( --dry-run
). Esto le mostrará lo que se eliminará sin eliminar realmente nada:
git clean -n -f -d
Ejemplo de salida:
Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...