Diferença entre “git checkout <filename>” e “git checkout - - <filename>”

Respostas:

214

A "opção" especial --significa "tratar cada argumento após este ponto como um nome de arquivo, não importa sua aparência." Isso não é específico do Git, é uma convenção geral de linha de comando do Unix. Normalmente você o usa para esclarecer que um argumento é um nome de arquivo em vez de uma opção , por exemplo

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

git checkout1 também --significa que os argumentos subsequentes não são seu parâmetro opcional "em árvore" especificando qual commit você deseja.

Portanto, neste contexto, é seguro usar --sempre, mas você precisa dele quando o arquivo que deseja reverter tem um nome que começa com -, ou é igual ao nome de um branch. Alguns exemplos para desambiguação de branch / arquivo:

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"

e desambiguação de opção / arquivo:

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"

Não tenho certeza do que você faz se tiver uma filial cujo nome começa com -. Talvez não faça isso em primeiro lugar.


1 neste modo; "checkout" pode fazer várias outras coisas também. Eu nunca entendi por que o git escolheu implementar "descartar alterações não confirmadas" como um modo do subcomando "checkout", em vez de "reverter" como a maioria dos outros VCSes, ou "redefinir", o que acho que pode fazer mais sentido nos termos do próprio git.

zwol
fonte
12
git checkout <name> verifica o branch <name>. git checkout - <name> verifica a versão do índice do arquivo <name>.
Dunni
3
Obrigado, infelizmente a documentação do git não explica isso
Carlton
1
Em relação à "convenção Unix": na verdade, --como um separador entre opções e argumentos é amplamente implementado. Ele funciona para qualquer programa / utilitário que use POSIX getopt(3)para lidar com suas opções de linha de comando (consulte man 3 getoptRecursos), scripts de shell que usam getopt(1)e alguns programas que os implementam, mas não é universalmente garantido que funcione.
arielf
Hah! Eu simplesmente li um exemplo de como descartar as alterações de trabalho, tendo esquecido de ver essa convenção em outros programas de linha de comando, assumido que --significava 'negar alterações' a la C / C ++ - e tenho pensado nisso desde então. Mente estourada!
sublinhado_d
Para pessoas como eu: não se confunda com o nome master, ele significa arquivo denominado master e não o branch.
HarsH
7

Qualquer coisa após o --é tratada como um nome de arquivo (não como um argumento de programa). Isso é importante se, por exemplo, você tiver nomes de arquivo que começam com travessões.

jtbandes
fonte