Significado dos traços duplos do check-out do Git

274

Qual é o significado dos traços duplos antes do nome do arquivo neste comando git?

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

Eles são obrigatórios? É equivalente a

git checkout --ours path/to/file.txt
git checkout --theirs path/to/file.txt
mottalrd
fonte
24
É uma expressão de concha. Veja unix.stackexchange.com/questions/11376/…
iltempo
15
@iltempo: É um pouco diferente para o Git. Para o Git, ele separa a árvore dos caminhos, nos casos em que árvores e caminhos podem ter a mesma aparência.
precisa
@Dietrich_Epp. Entendo. Obrigado por esclarecer.
Iltempo
Também documentado em stackoverflow.com/a/1192194/6309
VonC
3
É uma duplicata, mas essa duplicata é pelo menos passível de indexação pela consulta 'git double dash'.
Thorn

Respostas:

376

Suponha que eu tenha um arquivo nomeado path/to/file.txtno meu repositório Git e deseje reverter as alterações nele.

git checkout path/to/file.txt

Agora, suponha que o arquivo seja nomeado master...

git checkout master

Ops! Isso mudou os galhos. O --separa a árvore que você deseja retirar dos arquivos que deseja retirar.

git checkout -- master

Também nos ajuda se algum freako adicionou um arquivo chamado -fao nosso repositório:

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

Isso está documentado no git-checkout: Desambiguação de argumento .

Dietrich Epp
fonte
12
Isso é verdade para muitos comandos bash, não apenas para comandos git, sim?
NHDaly
40
@NHDaly: Sim, é verdade. No entanto, uma nota de terminologia: "Bash" possui apenas alguns comandos (talvez 20 ou mais), a maioria dos comandos são programas separados do Bash. Na verdade, é parte do padrão POSIX que --pode ser usado para separar opções de outros argumentos, portanto você o verá em comandos como cpe mv(que não fazem parte do Bash).
precisa
6
Alguma idéia de por que essa sintaxe não está descrita corretamente na checkoutdocumentação do comando?
TanguyP
4
@DietrichEpp Em vários lugares, ele é listado como um possível parâmetro para o checkoutcomando, mas em nenhum lugar a documentação explica o que faz ou por que é usado ... e foi isso que finalmente me trouxe aqui.
Chris
7
@DietrichEpp Correto, mas depois de ler a sintaxe (e os exemplos) antes de chegar ao Stack Overflow, ainda não entendi por que alguém iria ou não querer usar --. Como alguém que não é do fundo do Linux, não é óbvio o que isso faz. Para mim, parecia ser uma sintaxe específica do git, sem descrição de seu objetivo funcional. Eu acho que seria melhor ter uma descrição curta como as outras opções, ou pelo menos um link para uma página de manual do linux .
Chris
109

O traço duplo "-" significa "sinalizadores de fim de linha de comando", ou seja, diz ao comando anterior para não tentar analisar o que vem após as opções de linha de comando.

timmcliu
fonte
2
Para maior clareza, gitsignifica mais do que isso, pois também significa que o argumento após o --não pode ser um nome de filial e, por implicação, o argumento anterior --não pode ser um caminho de arquivo.
Gem Taylor
0

Observe que você não precisaria, desde o Git 2.5 (Q2 2015) a ' --' se seu argumento incluir curinga ( *)

Uma heurística para ajudar a " git <cmd> <revs> <pathspec>" convenção da linha de comando a pegar caminhos digitados incorretamente é garantir que todos os parâmetros que não sejam de rotação na parte posterior da linha de comando sejam nomes dos arquivos na árvore de trabalho, " git grep $str -- \*.c" mas isso sempre deve ser desambiguado com " --", porque ninguém sensato criará um arquivo cujo nome literalmente seja asterisco-ponto-ver.

O Git 2.5 perde a heurística para declarar que, com uma string curinga, o usuário provavelmente quis nos fornecer um pathspec .

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

Veja commit 28fcc0b (02 de maio de 2015) por Duy Nguyen ( nguyenlocduy) .
(Mesclado por Junio ​​C Hamano - gitster- na confirmação 949d167 , 19 de maio de 2015)

pathspec: evite a necessidade de " --" quando o curinga for usado

Quando " --" está ausente na linha de comando e um comando pode assumir rotações e caminhos, a idéia é se um argumento pode ser visto como um SHA-1 estendido e um caminho, " --" é necessário ou o git se recusa a continuar.
Atualmente, é implementado como:

  • (1) se um argumento é rev, ele não deve existir na árvore de trabalho
  • (2) caso contrário, ele deve existir na árvore de trabalho
  • (3) caso contrário, " --" é necessário.

Essas regras funcionam para caminhos literais, mas quando pathspec não literal está envolvido, quase sempre exige que o usuário adicione " --" porque falha em (2) e (1) raramente é atendido ( *.cpor exemplo, "take" ", por exemplo, (1) será atendido se houver uma ref chamada " *.c").

Esse patch modifica um pouco as regras, considerando qualquer *caminho curinga válido ( ) válido "existente na árvore de trabalho".
As regras se tornam:

  • (1) se um argumento é uma revisão, ele deve existir na árvore de trabalho ou não ser um código de caminho curinga válido.
  • (2) caso contrário, ele existe na árvore de trabalho ou é um caminho curinga
  • (3) caso contrário, " --" é necessário.

Com as novas regras, " --" não é necessário na maioria das vezes quando o pathspec curinga está envolvido.


Com o Git 2.26 (primeiro trimestre de 2020), a lógica de desambiguação para diferenciar revisões e pathspec foi alterada para que os caracteres especiais da glob escapados por barra invertida não sejam contados na regra "curingas são pathspec".

Veja commit 39e21c6 (25 de janeiro de 2020) por Jeff King ( peff) .
(Mesclado por Junio ​​C Hamano - gitster- na confirmação 341f8a6 , 12 de fevereiro de 2020)

verify_filename(): manipular barras invertidas na regra "curingas são pathspecs"

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

A confirmação 28fcc0b71a ( pathspec: evite a necessidade de " --" quando o curinga for usado, 02/05/2015) permitido:

git rev-parse '*.c'

sem o traço duplo.

Mas a regra usada para procurar curingas na verdade procura qualquer especial glob.
Isso é excessivamente liberal, pois significa que um padrão que realmente não faz nenhuma correspondência curinga, como " a\b", será considerado um pathspec.

Se você possui esse arquivo em disco, é provável que seja isso o que você queria.
Mas se não o fizer, os resultados serão confusos: em vez de dizer " there's no such path a\b", nós o aceitaremos silenciosamente como um caminho que provavelmente não corresponde a nada (ou pelo menos não ao que você pretendia).
Da mesma forma, procurar o caminho " a\*b" não expande a pesquisa; encontraria apenas uma única entrada " a*b".

Essa confirmação altera a regra para ser acionada apenas quando os metacaracteres globais expandirem a pesquisa, o que significa que os dois casos agora reportarão um erro (você ainda pode desambiguar usando " --", é claro; estamos apenas reforçando a heurística do DWIM).

( DWIM: faça o que eu quero dizer )

Observe que não testamos o recurso original em 28fcc0b71a .
Portanto, esse patch não apenas testa esses casos de canto, mas também adiciona um teste de regressão para o comportamento existente.

VonC
fonte