Signification des doubles tirets Git Checkout

274

Quelle est la signification des doubles tirets avant le nom de fichier dans cette commande git?

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

Sont-ils obligatoires? Est-ce équivalent à

git checkout --ours path/to/file.txt
git checkout --theirs path/to/file.txt
mottalrd
la source
24
C'est une expression shell. Voir unix.stackexchange.com/questions/11376/…
iltempo
15
@iltempo: C'est légèrement différent pour Git. Pour Git, cela sépare l'arbre des chemins, dans les cas où les arbres et les chemins peuvent se ressembler.
Dietrich Epp
@Dietrich_Epp. Je vois. Merci de clarifier.
iltempo
Également documenté dans stackoverflow.com/a/1192194/6309
VonC
3
C'est un doublon, mais ce doublon est au moins googleable par la requête 'git double dash'.
thorn̈

Réponses:

376

Supposons que j'ai un fichier nommé path/to/file.txtdans mon référentiel Git et que je souhaite annuler les modifications.

git checkout path/to/file.txt

Supposons maintenant que le fichier soit nommé master...

git checkout master

Oups! Cela a plutôt changé de branche. Le --sépare l'arborescence que vous souhaitez extraire des fichiers que vous souhaitez extraire.

git checkout -- master

Cela nous aide également si certains monstres ajoutent un fichier nommé -fà notre référentiel:

git checkout -f      # wrong
git checkout -- -f   # right

Ceci est documenté dans git-checkout: Argument Disambiguation .

Dietrich Epp
la source
12
Cela est vrai pour de nombreuses commandes bash, pas seulement pour les commandes git, oui?
NHDaly
40
@NHDaly: Oui, c'est vrai. Cependant, une note terminologique: "Bash" n'a que quelques commandes (peut-être une vingtaine), la plupart des commandes sont des programmes distincts de Bash. Il fait en fait partie du standard POSIX qui --peut être utilisé pour séparer les options des autres arguments, vous le verrez donc sur les commandes comme cpet mv(qui ne font pas partie de Bash).
Dietrich Epp
6
Une idée pourquoi cette syntaxe n'est pas correctement décrite dans la checkoutdocumentation de la commande?
TanguyP
4
@DietrichEpp À plusieurs endroits, il est répertorié comme un paramètre possible de la checkoutcommande, mais nulle part la documentation n'explique ce qu'il fait ou pourquoi il est utilisé ... ce qui m'a finalement amené ici.
chris
7
@DietrichEpp Correct, mais après avoir lu la syntaxe (et les exemples) avant d'arriver à Stack Overflow, je ne comprenais toujours pas pourquoi on voulait ou ne voulait pas utiliser --. En tant que personne qui ne vient pas d'un environnement Linux, ce n'est pas évident. Pour moi, cela semblait être une syntaxe spécifique à git, sans description de sa fonction. Je pense qu'il serait préférable d'avoir une courte description comme les autres options, ou au moins un lien vers une page de manuel Linux .
chris
109

Le double tiret «-» signifie «drapeaux de fin de ligne de commande», c'est-à-dire qu'il indique à la commande précédente de ne pas essayer d'analyser ce qui vient après les options de ligne de commande.

timmcliu
la source
2
Pour plus de clarté, gitcela signifie plus que cela, car cela signifie également que l'argument après --ne peut pas être un nom de branche, et par implication l'argument avant --ne peut pas être un chemin de fichier.
Gem Taylor
0

Notez que vous n'auriez pas besoin, puisque Git 2.5 (Q2 2015) d'un ' --' si votre argument inclut un caractère générique ( *)

Une heuristique pour aider la " git <cmd> <revs> <pathspec>" convention de ligne de commande à capturer les chemins mal typés est de s'assurer que tous les paramètres non rev dans la dernière partie de la ligne de commande sont les noms des fichiers dans l'arborescence de travail, mais cela signifie que " git grep $str -- \*.c" doit toujours être sans ambiguïté avec " --", car personne sain d'esprit ne créera un fichier dont le nom est littéralement astérisque-point-voir.

Git 2.5 perd l'heuristique pour déclarer qu'avec une chaîne générique, l'utilisateur voulait probablement nous donner une spécification de chemin .

git checkout 'a*'
# same as
git checkout -- 'a*'

Voir commit 28fcc0b (02 mai 2015) par Duy Nguyen ( nguyenlocduy) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 949d167 , 19 mai 2015)

pathspec: éviter le besoin de " --" lorsque le caractère générique est utilisé

Lorsque " --" est absent de la ligne de commande et qu'une commande peut prendre à la fois des tours et des chemins, l'idée est que si un argument peut être vu à la fois comme un SHA-1 étendu et un chemin, " --" est requis ou git refuse de continuer.
Il est actuellement implémenté comme:

  • (1) si un argument est rev, alors il ne doit pas exister dans worktree
  • (2) sinon, il doit exister dans worktree
  • (3) sinon, " --" est requis.

Ces règles fonctionnent pour les chemins littéraux, mais lorsqu'une spécification de chemin non littérale est impliquée, elle oblige presque toujours l'utilisateur à ajouter " --" car elle échoue (2) et (1) est vraiment rarement respectée (prenez " *.c" par exemple, (1) est satisfaite s'il existe une référence nommée " *.c").

Ce correctif modifie un peu les règles en considérant toute *spécification de chemin de caractères génériques valide ( ) "existe dans le worktree".
Les règles deviennent:

  • (1) si un argument est un rev, alors il doit exister dans worktree ou ne pas être une spécification de chemin générique valide.
  • (2) sinon, il existe dans worktree ou est un caractère générique pathspec
  • (3) sinon, " --" est requis.

Avec les nouvelles règles, " --" n'est plus nécessaire la plupart du temps lorsque le caractère générique pathspec est impliqué.


Avec Git 2.26 (Q1 2020), la logique de désambiguïsation pour distinguer les révisions et les pathspec a été modifiée de sorte que les caractères spéciaux glob échappés de barre oblique inverse ne comptent pas dans la règle "les caractères génériques sont des pathspec".

Voir commit 39e21c6 (25 janvier 2020) de Jeff King ( peff) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 341f8a6 , 12 fév 2020)

verify_filename(): gérer les barres obliques inverses dans la règle "les caractères génériques sont des chemins d'accès"

Signalé par: David Burström
Signé par: Jeff King

Commit 28fcc0b71a ( pathspec: évitez d'avoir besoin de " --" lorsque le caractère générique est utilisé, 2015-05-02) autorisé:

git rev-parse '*.c'

sans le double tiret.

Mais la règle qu'il utilise pour vérifier les caractères génériques recherche en fait n'importe quelle spéciale de glob.
C'est trop libéral, car cela signifie qu'un modèle qui ne fait aucune correspondance générique, comme " a\b", sera considéré comme une spécification de chemin.

Si vous avez un tel fichier sur le disque, c'est probablement ce que vous vouliez.
Mais si vous ne le faites pas, les résultats sont déroutants: plutôt que de dire " there's no such path a\b", nous l'accepterons tranquillement comme une pathspec qui ne correspond probablement à rien (ou du moins pas à ce que vous vouliez).
De même, la recherche du chemin " a\*b" n'élargit pas du tout la recherche; il ne trouverait qu'une seule entrée, " a*b".

Cette validation commute la règle pour qu'elle ne se déclenche que lorsque les métacaractères glob élargissent la recherche, ce qui signifie que ces deux cas signaleront désormais une erreur (vous pouvez toujours lever l'ambiguïté en utilisant " --", bien sûr; nous resserrons simplement l'heuristique DWIM).

( DWIM: Faites ce que je veux dire )

Notez que nous n'avons pas du tout testé la fonctionnalité d'origine dans 28fcc0b71a .
Ce correctif teste donc non seulement ces cas d'angle, mais ajoute également un test de régression pour le comportement existant.

VonC
la source