Différence entre «git checkout <filename>» et «git checkout - - <filename>»

Réponses:

214

L'option spéciale --signifie «traiter chaque argument après ce point comme un nom de fichier, peu importe à quoi il ressemble». Ce n'est pas spécifique à Git, c'est une convention générale de ligne de commande Unix. Normalement, vous l'utilisez pour clarifier qu'un argument est un nom de fichier plutôt qu'une option , par exemple

rm -f      # does nothing
rm -- -f   # deletes a file named "-f"

git checkout1 prend également --signifier que les arguments suivants ne sont pas le paramètre optionnel spécifiant « de treeish » que vous voulez engager.

Donc, dans ce contexte, il est toujours sûr de l'utiliser --, mais vous en avez besoin lorsque le fichier que vous souhaitez restaurer a un nom qui commence par -ou est le même que le nom d'une branche. Quelques exemples d'homonymie de branche / fichier:

git checkout README     # would normally discard uncommitted changes
                        # to the _file_ "README"

git checkout master     # would normally switch the working copy to
                        # the _branch_ "master"

git checkout -- master  # discard uncommitted changes to the _file_ "master"

et désambiguïsation des options / fichiers:

git checkout -p -- README  # interactively discard uncommitted changes
                           # to the file "README"

git checkout -- -p README  # unconditionally discard all uncommitted
                           # changes to the files "-p" and "README"

Je ne sais pas ce que vous faites si vous avez une succursale dont le nom commence par -. Peut-être ne faites pas cela en premier lieu.


1 dans ce mode; "checkout" peut également faire plusieurs autres choses. Je n'ai jamais compris pourquoi git a choisi d'implémenter "rejeter les modifications non validées" comme mode de la sous-commande "checkout", plutôt que "revert" comme la plupart des autres VCS, ou "reset" qui, je pense, pourrait avoir plus de sens dans les propres termes de git.

zwol
la source
12
git checkout <nom> vérifie la branche <nom>. git checkout - <nom> extrait la version d'index du fichier <nom>.
dunni le
3
Merci, malheureusement, la documentation git n'explique pas vraiment cela
Carlton
1
Concernant la "convention Unix": en effet --comme séparateur entre les options et les arguments est largement implémenté. Il fonctionne pour tout programme / utilitaire qui utilise POSIX getopt(3)pour gérer ses options de ligne de commande, (voirman 3 getopt ), les scripts shell qui l'utilisent getopt(1)et certains programmes qui l'implémentent eux-mêmes, mais son fonctionnement n'est pas garanti universellement .
arielf
Hah! J'ai simplement lu un exemple de la façon de supprimer les changements de travail, ayant oublié de voir cette convention dans d'autres programmes de ligne de commande, supposé que cela --signifiait `` annuler les changements '' à la C / C ++ - et je le pense depuis. L'esprit soufflé!
underscore_d
Pour les gens comme moi: ne vous méprenez pas sur le nom du maître, il veut dire le fichier nommé maître et non la branche.
HarsH
7

Tout ce qui suit --est traité comme un nom de fichier (et non comme un argument de programme). Ceci est important si, par exemple, vous avez des noms de fichiers commençant par des tirets.

jtbandes
la source