Significado de Git checkout dobles guiones

274

¿Cuál es el significado de los guiones dobles antes del nombre del archivo en este comando git?

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

¿Son obligatorios? ¿Es equivalente a

git checkout --ours path/to/file.txt
git checkout --theirs path/to/file.txt
mottalrd
fuente
24
Es una expresión de concha. Ver unix.stackexchange.com/questions/11376/…
iltempo
15
@iltempo: es un poco diferente para Git. Para Git, separa el árbol de los caminos, en los casos en que los árboles y los caminos podrían tener el mismo aspecto.
Dietrich Epp
@Dietrich_Epp. Veo. Gracias por aclararlo.
iltempo
También documentado en stackoverflow.com/a/1192194/6309
VonC
3
Es un duplicado, pero este duplicado es al menos googleable por la consulta 'git double dash'.
thorn̈

Respuestas:

376

Supongamos que tengo un archivo llamado path/to/file.txten mi repositorio de Git y quiero revertir los cambios en él.

git checkout path/to/file.txt

Ahora suponga que el archivo se llama master...

git checkout master

Whoops! Eso cambió las ramas en su lugar. Los --separa el árbol que desee comprobar hacia fuera a partir de los archivos que desea retirar.

git checkout -- master

También nos ayuda si algún freako agregó un archivo llamado -fa nuestro repositorio:

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

Esto está documentado en git-checkout: Argument Disambiguation .

Dietrich Epp
fuente
12
Esto es cierto para muchos comandos bash, no solo para los comandos git, ¿sí?
NHDaly
40
@NHDaly: Sí, es verdad. Sin embargo, una nota de terminología: "Bash" solo tiene unos pocos comandos (quizás 20 o más), la mayoría de los comandos son programas separados de Bash. En realidad, es parte del estándar POSIX que --se puede usar para separar las opciones de otros argumentos, por lo que lo verá en comandos como cpy mv(que no son parte de Bash).
Dietrich Epp
66
¿Alguna idea de por qué esta sintaxis no se describe correctamente en la checkoutdocumentación del comando?
TanguyP
44
@DietrichEpp En varios lugares, se enumera como un posible parámetro para el checkoutcomando, pero en ningún lugar la documentación explica qué hace o por qué se usa ... que es lo que finalmente me trajo aquí.
Chris
77
@DietrichEpp Correcto, pero después de leer la sintaxis (y los ejemplos) antes de llegar a Stack Overflow, todavía no entendía por qué uno querría o no usar --. Como alguien que no proviene de un entorno Linux, no es obvio lo que hace. Para mí, parecía ser una sintaxis específica de git, sin una descripción de su propósito funcional. Creo que sería mejor tener una breve descripción como las otras opciones, o al menos un enlace a una página de manual de Linux .
Chris
109

El guión doble "-" significa "marcas de fin de línea de comando", es decir, le dice al comando anterior que no intente analizar lo que viene después de las opciones de línea de comando.

timmcliu
fuente
2
Para mayor claridad, gitsignifica más que esto, ya que también significa que el argumento después del --no puede ser un nombre de rama, y ​​por implicación el argumento anterior --no puede ser una ruta de archivo.
Gem Taylor
0

Tenga en cuenta que no necesitaría, ya que Git 2.5 (Q2 2015) a ' --' si su argumento incluye comodín ( *)

Una "heurística para ayudar a la" git <cmd> <revs> <pathspec>"convención de línea de comandos para atrapar rutas mal escritas es asegurarse de que todos los parámetros que no sean de revoluciones en la parte posterior de la línea de comandos sean nombres de los archivos en el árbol de trabajo, pero eso significa" git grep $str -- \*.c"siempre debe ser desambiguado con " --", porque nadie cuerdo creará un archivo cuyo nombre literalmente es asterisco-punto-ver.

Git 2.5 pierde la heurística para declarar que con una cadena comodín el usuario probablemente tenía la intención de darnos una especificación de ruta .

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

Ver commit 28fcc0b (02 de mayo de 2015) por Duy Nguyen ( nguyenlocduy) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 949d167 , 19 de mayo de 2015)

pathspec: evite la necesidad de " --" cuando se usa comodín

Cuando " --" no se encuentra en la línea de comando y un comando puede tomar tanto revoluciones como rutas, la idea es si un argumento puede verse como un SHA-1 extendido y como una ruta, entonces --se requiere " " o git se niega a continuar.
Actualmente se implementa como:

  • (1) si un argumento es rev, entonces no debe existir en worktree
  • (2) de lo contrario, debe existir en worktree
  • (3) de lo contrario, " --" es obligatorio.

Estas reglas funcionan para rutas literales, pero cuando se trata de rutas no literales, casi siempre requiere que el usuario agregue " --" porque falla (2) y (1) realmente rara vez se cumple (tome " *.c" por ejemplo, (1) se cumple si hay una referencia denominada " *.c").

Este parche modifica un poco las reglas al considerar cualquier *especificación de ruta comodín válida ( ) "existe en el árbol de trabajo".
Las reglas se convierten en:

  • (1) si un arg es una rev, debe existir en el árbol de trabajo o no ser una ruta de acceso comodín válida.
  • (2) de lo contrario, existe en worktree o es un comodín pathpec
  • (3) de lo contrario, " --" es obligatorio.

Con las nuevas reglas, " --" no es necesario la mayor parte del tiempo cuando se trata de comodines de ruta específica.


Con Git 2.26 (Q1 2020), la lógica de desambiguación para distinguir las revisiones y las rutas específicas se ha modificado para que los caracteres especiales de globo de escape con barra invertida no cuenten en la regla "los comodines son rutas específicas".

Ver commit 39e21c6 (25 de enero de 2020) por Jeff King ( peff) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 341f8a6 , 12 de febrero de 2020)

verify_filename(): manejar barras diagonales inversas en la regla "los comodines son pathpecs"

Reportado por: David Burström
Firmado por: Jeff King

El commit 28fcc0b71a ( pathspec: evita la necesidad de " --" cuando se usa el comodín, 2015-05-02) permitido:

git rev-parse '*.c'

sin el doble guión.

Pero la regla que usa para buscar comodines en realidad busca cualquier glob especial.
Esto es demasiado liberal, ya que significa que un patrón que en realidad no coincida con comodines, como " a\b", se considerará una especificación de ruta.

Si tiene un archivo de este tipo en el disco, presumiblemente eso es lo que quería.
Pero si no lo hace, los resultados son confusos: en lugar de decir " there's no such path a\b", lo aceptaremos en silencio como una especificación de ruta que probablemente no coincida con nada (o al menos no con lo que pretendía).
Del mismo modo, buscar la ruta " a\*b" no amplía la búsqueda en absoluto; solo encontraría una sola entrada, " a*b".

Esta confirmación cambia la regla para que se active solo cuando los metacaracteres glob expandirían la búsqueda, lo que significa que ambos casos ahora informarán un error (todavía puede desambiguar usando " --", por supuesto; solo estamos ajustando la heurística DWIM).

( DWIM: Haz lo que quiero decir )

Tenga en cuenta que no probamos la característica original en 28fcc0b71a en absoluto.
Entonces, este parche no solo prueba estos casos de esquina, sino que también agrega una prueba de regresión para el comportamiento existente.

VonC
fuente