O que é a flag --end-of-options do git

Existe um problema clássico em ferramentas de linha de comando: e se um nome de arquivo começar com hífen? O shell e o programa interpretam o argumento como uma opcao em vez de um nome de arquivo, causando erros confusos ou comportamentos inesperados.

O git resolveu isso com a flag --end-of-options. Quando você coloca --end-of-options antes de um argumento, você esta dizendo ao git: tudo que vem depois disso e um nome de arquivo ou commit, não uma opcao.

Essa flag existe em vários programas POSIX ha décadas na forma de --, mas o git adicionou a versão nomeada --end-of-options para deixar o comportamento mais explicito e legível. Parece um detalhe pequeno, mas tem implicações reais de segurança em scripts e pipelines de CI/CD.

Como o problema acontece na prática

Imagine que alguém cria uma branch com o nome -f ou --all. Quando você passa esse valor para um comando git sem cuidado, o programa pode interpretar como uma opcao em vez do argumento que você queria.

Um caso mais prático: em pipelines de CI/CD, o nome da branch muitas vezes vem de uma variável de ambiente controlada por quem abre um pull request. Se o pipeline faz git checkout $BRANCH_NAME sem cuidado, um nome de branch malicioso poderia injetar opcoes no comando git.

O --end-of-options e a forma mais limpa de resolver isso: git checkout --end-of-options "$BRANCH_NAME" garante que o valor sempre seja tratado como um nome de branch, não como opcoes.

⚠️
Atenção

Em scripts de CI/CD que usam variáveis de ambiente para nomes de branch, commit ou arquivo, use sempre --end-of-options ou -- para separar opcoes de argumentos. E uma prática de segurança, não apenas de estilo.

A diferença entre -- e --end-of-options

O git tem dois separadores parecidos mas com comportamentos diferentes.

-- (duplo traço): separa opcoes de nomes de arquivos. Muito usado para evitar ambiguidade com arquivos que começam com hífen. Exemplo: git checkout -- arquivo.txt garante que arquivo.txt e um caminho, não uma branch.

--end-of-options: mais explicito e mais amplo. Sinaliza que tudo após este ponto e um argumento posicional, seja nome de arquivo, commit, branch ou qualquer coisa. Mais legível em scripts longos.

💡
Dica

Em scripts, prefira --end-of-options pela legibilidade. Em uso interativo no terminal, -- e mais rápido de digitar e amplamente entendido pela comunidade.

Como usar: exemplos práticos

Veja situações reais onde essa flag faz diferença:

# Sem --end-of-options: pode falhar se $ARQUIVO começar com hífen
git add $ARQUIVO

# Com --end-of-options: seguro independente do nome
git add --end-of-options "$ARQUIVO"

# Em CI/CD com variável de ambiente para branch
# Inseguro:
git checkout "$BRANCH_NAME"

# Seguro:
git checkout --end-of-options "$BRANCH_NAME"

# Mostrando diff de arquivo com nome esquisito
git diff -- -v

# Verificar commit hash vindo de variável
git show --end-of-options "$COMMIT_HASH"

Uma situação clássica e a diferença entre git checkout branch e git checkout -- arquivo. O -- diz ao git que o próximo argumento e um caminho de arquivo. O --end-of-options e mais explicito sobre essa intenção.

🚀
Pro tip

Quando escrever scripts que aceitam entradas do usuário e as passam para comandos git, adicione --end-of-options como regra automática. O custo e zero e a proteção contra inputs inesperados e real.

Comparação: git vs outros comandos POSIX

O padrão POSIX define que -- deve finalizar o processamento de opcoes em qualquer utilitário de linha de comando. Esse comportamento existe ha décadas em ls, grep, cp, mv e outros comandos Unix.

O --end-of-options e específico do git e foi adicionado para tornar o comportamento mais explicito. A diferença prática: ls -- -arquivo funciona para listar um arquivo chamado -arquivo. git log --end-of-options -abc123 mostraria o commit -abc123 sem interpretar como opcao.

O conceito e o mesmo, a sintaxe do git e mais legível para quem le scripts complexos.

Pontos positivos e limitações

O --end-of-options resolve de forma limpa um problema real de ambiguidade. E mais legível que --, funciona nos subcomandos principais do git, e a intenção fica clara para quem le o script depois.

As limitações são mínimas: nem todo subcomando do git suporta --end-of-options (alguns mais antigos só reconhecem --), e em uso interativo no terminal digitar a flag completa e menos eficiente. Para uso em scripts, onde a clareza importa mais, e a escolha certa.

O suporte foi adicionado de forma consistente nas versões modernas do git. Se você estiver em um ambiente muito antigo (git anterior a 2.24), use -- como alternativa compatível.

Casos de uso reais

Pipelines de CI/CD: qualquer pipeline que usa o nome da branch como variável em comandos git se beneficia. GitHub Actions, GitLab CI e Jenkins passam o nome da branch como variável de ambiente.

Scripts de automação de repositório: scripts que fazem checkout, merge, tag ou push com base em entradas externas devem usar essa flag por padrão.

Ferramentas de CLI que chamam git internamente: se você esta escrevendo uma CLI em Python ou Go que chama subprocessos git, proteja as chamadas com --end-of-options antes de qualquer argumento que venha de entrada do usuário.

Hooks do git: pre-commit, pre-push e outros hooks que executam comandos git com nomes de arquivo ou referência passados como argumentos se tornam mais robustos com essa prática.

Dicas e boas práticas

💡
Dica

Crie um alias no seu .bashrc ou .zshrc para os comandos git mais usados com variáveis: alias gco='git checkout --end-of-options'. Você ganha a proteção sem ter que digitar a flag toda vez.

⚠️
Atenção

Mesmo com --end-of-options, sempre valide entradas do usuário em scripts críticos. A flag protege contra interpretação incorreta como opcoes, mas não contra outros tipos de inputs maliciosos como path traversal.

🔴
Cuidado

Nunca use interpolação de variáveis sem aspas em comandos git em shell scripts: git checkout $BRANCH pode sofrer word splitting. Sempre use aspas: git checkout --end-of-options "$BRANCH".

Vale a pena usar git --end-of-options?

Sim, especialmente em qualquer contexto automatizado. Em uso interativo, o -- já e suficiente e mais rápido de digitar. Mas em scripts, pipelines e ferramentas que passam argumentos dinâmicos para o git, adotar --end-of-options como padrão e uma decisão de qualidade que custa zero.

A maioria dos problemas causados por essa ambiguidade aparece raramente, o que significa que quando aparecem são difíceis de diagnosticar. Prevenir com uma flag e muito mais barato que debugar um pipeline de CI/CD com comportamento esquisito.

O próximo passo e revisar seus scripts que chamam git com variáveis e adicionar a flag onde ela esta faltando. Uma busca rápida por git checkout $ ou git add $ no seu repositório de scripts e um bom ponto de partida.