Respuestas:
Porque no tiene sentido (otros comandos ya proporcionan esa funcionalidad), y reduce la posibilidad de hacer algo incorrecto por accidente.
Acaba de hacer un "restablecimiento git checkout HEAD -- <path>
completo " para una ruta (verificando la versión existente del archivo).
Un restablecimiento parcial de una ruta no tiene sentido.
Un restablecimiento mixto para una ruta es lo que git reset -- <path>
hace.
git checkout -- <path>
no hace un restablecimiento completo; reemplaza el contenido del árbol de trabajo con el contenido en etapas. git checkout HEAD -- <path>
realiza un restablecimiento completo para una ruta, reemplazando tanto el índice como el árbol de trabajo con la versión de la confirmación HEAD.
reset --hard
con un camino proporcionaría esta pieza que falta. Git ya es tan poderoso que la excusa "No dejamos que hagas esto por tu propia protección" no tiene agua: hay muchas maneras de hacer lo incorrecto "por accidente". Nada de eso importa de todos modos cuando lo tienes git reflog
.
git reset --hard -- <path>
. Hay casos de uso legítimo para ello.
Puedes lograr lo que estás tratando de hacer usando git checkout HEAD <path>
.
Dicho esto, el mensaje de error proporcionado no tiene sentido para mí (ya que git reset
funciona bien en subdirectorios), y no veo ninguna razón por la git reset --hard
que no deba hacer exactamente lo que le está pidiendo.
La pregunta de cómo ya está respondida , explicaré la parte del por qué .
Entonces, ¿qué hace git reset ? Dependiendo de los parámetros especificados, puede hacer dos cosas diferentes:
Si especifica una ruta, reemplaza los archivos coincidentes en el índice con los archivos de una confirmación (HEAD de forma predeterminada). Esta acción no afecta en absoluto el árbol de trabajo y generalmente se usa como lo contrario de git add.
Si no especifica una ruta, mueve la cabeza de la rama actual a una confirmación especificada y, junto con eso , opcionalmente restablece el índice y el árbol de trabajo al estado de esa confirmación. Este comportamiento adicional está controlado por el parámetro de modo:
--soft : no toque el índice ni el árbol de trabajo.
--mixed (predeterminado): restablece el índice pero no el árbol de trabajo.
--hard : restablece el índice y el árbol de trabajo.
También hay otras opciones, consulte la documentación para ver la lista completa y algunos casos de uso.
Cuando no especifica una confirmación, el valor predeterminado es HEAD, por git reset --soft
lo que no hará nada, ya que es un comando para mover la cabeza a HEAD (a su estado actual). git reset --hard
, por otro lado, tiene sentido debido a sus efectos secundarios , dice mover la cabeza a HEAD y restablecer el índice y el árbol de trabajo a HEAD.
Creo que ya debería estar claro por qué esta operación no es para archivos específicos por su naturaleza: en primer lugar, está destinada a mover un encabezado de rama, restablecer el árbol de trabajo y el índice es una funcionalidad secundaria.
git checkout
comando? Y hacer un reinicio para hacer lo mismo confundiría aún más a los usuarios. Mi respuesta fue que esa --hard
opción no es aplicable a archivos específicos porque es un modo de restablecimiento de rama, no restablecimiento de índice. Y el reinicio del árbol de trabajo se denomina pago, como puede leer en otras respuestas. Todo eso es solo un mal diseño de la interfaz de usuario de Git, en mi humilde opinión.
git checkout
: git reset --
establece solo el índice, mientras git checkout --
establece solo el árbol de trabajo?
Asegúrese de poner una barra diagonal entre el origen o el flujo ascendente (fuente) y la rama real:
git reset --hard origin/branch
o
git reset --hard upstream/branch`
Hay una razón muy importante detrás de eso: los principios de checkout
yreset
.
En términos de Git, pagar significa "traer al árbol de trabajo actual". Y con git checkout
nosotros podemos llenar el árbol de trabajo con datos de cualquier área, ya sea desde un commit en el repositorio o archivos individuales desde un commit o el área de ensayo (que es el valor predeterminado).
A su vez, git reset no tiene esta función. Como su nombre indica, restablecerá la referencia actual pero siempre tendrá el repositorio como fuente, independientemente del "alcance" (--soft, --mixed o --hard).
Resumen:
Por lo tanto, lo que puede ser un poco confuso es la existencia de, git reset COMMIT -- files
ya que "sobrescribir HEAD" con solo algunos archivos no tiene sentido.
En ausencia de una explicación oficial, solo puedo especular que los desarrolladores de git descubrieron que reset
todavía era el mejor nombre de un comando para descartar los cambios realizados en el área de preparación y, dado que la única fuente de datos era el repositorio, entonces " ampliemos el funcionalidad "en lugar de crear un nuevo comando.
Entonces, de alguna manera git reset -- <files>
ya es un poco excepcional: no sobrescribirá el HEAD. En mi humilde opinión, todas esas variaciones serían excepciones. Incluso si podemos concebir una --hard
versión, otras (por ejemplo --soft
) no tendrían sentido.
git reset -- <files>
cayó como si se hubiera agregado porque esta es una característica útil, pero nadie estaba seguro de en qué comando se debería poner. Afortunadamente, ahora tenemos mucho más sano git restore
que tiene una funcionalidad git checkout -- <path>
git checkout <commit> -- <path>
y git reset [<commit>] -- <path>
con valores predeterminados mucho más sanos e incluso más funciones que no podía hacer antes (Contrariamente a lo que dice la respuesta aceptada. Ahora finalmente puede restaurar fácilmente el árbol de trabajo, sin tocar el índice).
El git reset
manual enumera 3 formas de invocación:
2 son de archivo: estos no afectan el árbol de trabajo , pero operan solo en los archivos en el índice especificado por <paths>
:
git reset [-q] [<tree-ish>] [--] <paths>..
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
1 es commit-wise: funciona en todos los archivos de la referencia <commit>
y puede afectar el árbol de trabajo:
git reset [<mode>] [<commit>]
No hay ningún modo de invocación que funcione solo en archivos específicos y afecte al árbol de trabajo.
Si quieres ambos:
Puede usar este alias en su archivo de configuración de git:
[alias]
reco = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #" # Avoid: "fatal: Cannot do hard reset with paths."
Luego puede hacer uno de:
$ git reco <paths>
$ git reco <branch/commit> <paths>
$ git reco -- <paths>
(Mnenonic para reco
: re
set && c
heck o
ut)
git checkout -- <path>
debería ser reemplazado porgit reset --hard <path>
. Tiene mucho más sentido ...