Réponses:
Parce que cela ne sert à rien (d'autres commandes fournissent déjà cette fonctionnalité), et cela réduit le risque de faire la mauvaise chose par accident.
Un "hard reset" pour un chemin est juste fait avec git checkout HEAD -- <path>
(vérification de la version existante du fichier).
Une réinitialisation logicielle pour un chemin n'a pas de sens.
Une réinitialisation mixte pour un chemin est ce que git reset -- <path>
fait.
git checkout -- <path>
ne fait pas de réinitialisation matérielle; il remplace le contenu de l'arborescence de travail par le contenu mis en scène. git checkout HEAD -- <path>
effectue une réinitialisation matérielle pour un chemin, en remplaçant à la fois l'index et l'arborescence de travail par la version du commit HEAD.
reset --hard
avec un chemin fournirait cette pièce manquante. Git est déjà si puissant que l'excuse "Nous ne vous laissons pas faire cela pour votre propre protection" ne contient aucune eau: il existe de nombreuses façons de faire la mauvaise chose "par accident". Rien de tout cela n'a d'importance de toute façon quand vous en avez git reflog
.
git reset --hard -- <path>
. Il existe des cas d'utilisation légitimes pour cela.
Vous pouvez accomplir ce que vous essayez de faire en utilisant git checkout HEAD <path>
.
Cela dit, le message d'erreur fourni n'a aucun sens pour moi (car git reset
fonctionne très bien sur les sous-répertoires), et je ne vois aucune raison pour laquelle git reset --hard
ne devrait pas faire exactement ce que vous lui demandez.
La question comment est déjà répondu , je vais expliquer la partie pourquoi .
Alors, que fait git reset ? Selon les paramètres spécifiés, il peut faire deux choses différentes:
Si vous spécifiez un chemin, il remplace les fichiers correspondants dans l'index par les fichiers d'un commit (HEAD par défaut). Cette action n'affecte pas du tout l'arbre de travail et est généralement utilisée comme l'opposé de git add.
Si vous ne spécifiez pas de chemin, il déplace la tête de branche actuelle vers un commit spécifié et, avec cela , réinitialise éventuellement l'index et l'arborescence de travail à l'état de ce commit. Ce comportement supplémentaire est contrôlé par le paramètre mode:
--soft : ne touchez pas l'index et l'arbre de travail.
--mixed (par défaut): réinitialise l'index mais pas l'arborescence de travail.
--hard : réinitialise l'index et l'arbre de travail.
Il existe également d'autres options, voir la documentation pour la liste complète et quelques cas d'utilisation.
Lorsque vous ne spécifiez pas de validation, la valeur par défaut est HEAD, donc git reset --soft
ne fera rien, car il s'agit d'une commande pour déplacer la tête vers HEAD (à son état actuel). git reset --hard
, d'autre part, a du sens en raison de ses effets secondaires , il dit de déplacer la tête vers HEAD et de réinitialiser l'index et l'arbre de travail sur HEAD.
Je pense qu'il devrait être clair maintenant pourquoi cette opération n'est pas destinée à des fichiers spécifiques de par sa nature - elle est destinée à déplacer une tête de branche en premier lieu, en réinitialisant l'arbre de travail et l'index est une fonctionnalité secondaire.
git checkout
commande? Et faire une réinitialisation pour faire la même chose dérouterait davantage les utilisateurs. Ma réponse a été que l' --hard
option n'est pas applicable à des fichiers spécifiques car il s'agit d'un mode de réinitialisation de branche, pas de réinitialisation d'index. Et la réinitialisation de l'arbre de travail s'appelle checkout, comme vous pouvez le lire dans d'autres réponses. Tout cela n'est qu'une mauvaise conception de l'interface utilisateur de Git, à mon humble avis.
git checkout
: git reset --
définit uniquement l'index, tandis que git checkout --
définit uniquement l'arborescence de travail?
Assurez-vous de mettre une barre oblique entre l'origine ou l'amont (source) et la branche réelle:
git reset --hard origin/branch
ou
git reset --hard upstream/branch`
Il y a une raison très importante derrière cela: les principes de checkout
etreset
.
En termes Git, checkout signifie "intégrer l'arborescence de travail actuelle". Et avec, git checkout
nous pouvons remplir l'arborescence de travail avec des données de n'importe quelle zone, qu'il s'agisse d'un commit dans le référentiel ou de fichiers individuels d'un commit ou de la zone de préparation (qui est même la valeur par défaut).
À son tour, git reset n'a pas ce rôle. Comme son nom l'indique, il réinitialisera la référence actuelle mais en ayant toujours le référentiel comme source, indépendamment du "reach" (--soft, --mixed ou --hard).
Résumer:
Par conséquent, ce qui peut être un peu déroutant, c'est l'existence de git reset COMMIT -- files
car "écraser HEAD" avec seulement quelques fichiers n'a pas de sens!
En l'absence d'explication officielle, je ne peux que spéculer que les développeurs git ont trouvé que reset
c'était toujours le meilleur nom d'une commande pour annuler les modifications apportées à la zone de préparation et, étant donné que la seule source de données était le référentiel, alors " étendons le fonctionnalité »au lieu de créer une nouvelle commande.
C'est donc git reset -- <files>
déjà un peu exceptionnel: il n'écrasera pas la HEAD. IMHO toutes ces variations seraient des exceptions. Même si nous pouvons concevoir une --hard
version, d'autres (par exemple --soft
) n'auraient pas de sens.
git reset -- <files>
tombé comme si elle avait été ajoutée car c'est une fonctionnalité utile, mais personne ne savait dans quelle commande elle devait être placée. Heureusement, nous avons maintenant beaucoup plus sains d'esprit git restore
qui ont des fonctionnalités git checkout -- <path>
git checkout <commit> -- <path>
et des git reset [<commit>] -- <path>
valeurs par défaut beaucoup plus saines et encore plus de fonctionnalités que vous ne pouviez pas faire auparavant (contrairement à ce que dit la réponse acceptée. Maintenant, vous pouvez enfin restaurer facilement l'arbre de travail, sans toucher à l'index).
Le git reset
manuel répertorie 3 modes d'appel:
2 sont au niveau des fichiers: ils n'affectent pas l'arborescence de travail , mais fonctionnent uniquement sur les fichiers de l'index spécifié par <paths>
:
git reset [-q] [<tree-ish>] [--] <paths>..
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
1 est commise: fonctionne sur tous les fichiers référencés <commit>
et peut affecter l'arborescence de travail:
git reset [<mode>] [<commit>]
Il n'y a pas de mode d'appel qui n'opère que sur les fichiers spécifiés et affecte l'arborescence de travail.
Si vous voulez les deux:
Vous pouvez utiliser cet alias dans votre fichier de configuration git:
[alias]
reco = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #" # Avoid: "fatal: Cannot do hard reset with paths."
Vous pouvez ensuite effectuer l'une des opérations suivantes:
$ git reco <paths>
$ git reco <branch/commit> <paths>
$ git reco -- <paths>
(Mnenonic pour reco
: re
set && c
heck o
ut)
git checkout -- <path>
devrait être remplacé pargit reset --hard <path>
. Ça a tellement plus de sens ...