Quando usar barra inicial no gitignore

108

Estou tentando entender mais claramente a .gitignoresintaxe e, em particular, no que diz respeito a https://github.com/github/gitignore gitignores.

Vejo que a barra inicial é usada para corresponder apenas aos nomes de caminho relativos à localização do .gitignorearquivo (de http://git-scm.com/docs/gitignore ):

Uma barra inicial corresponde ao início do nome do caminho. Por exemplo, "/*.c" corresponde a "cat-file.c", mas não a "mozilla-sha1 / sha1.c".

Mas o que acontece quando eu removo a barra inicial? Pelo que entendi, são dois casos:

  1. Se o padrão não contém uma barra (ou contém apenas uma barra final, o que significa que deve corresponder a um diretório), a pesquisa é realizada dentro de toda a árvore de diretórios. Por exemplo, o padrão dir/irá corresponder <root>/dir, <root>/a/dir, <root>/a/b/c/.../dir, etc., onde <root>é a localização do .gitignorearquivo.
  2. Se o padrão contém uma barra, que não está na posição final (não é o último caractere), então ele é correspondido apenas com os nomes de caminho relativos à .gitignorelocalização do arquivo.

Estes são os exemplos que fiz para verificar esse comportamento:

# Directory structure:
<root>
├─ dir/
│   └─ test
├─ src/
│   ├─ dir/
│   │   └─ test
test file is there only because Git does not track empty directories.

Primeiro teste:

# .gitignore
dir/

# git status
nothing to commit

Portanto, o Git está ignorando os dois dirdiretórios. Isso é consistente com o caso número 1: o padrão não tem barras (exceto a barra final), então o Git está observando toda a árvore de diretório, ignorando tudo que corresponde ao padrão.

Segundo teste:

# .gitignore
/dir/

# git status
Untracked files:
    src/

Aqui, o Git está ignorando apenas o dirdiretório diretamente abaixo do diretório raiz, graças à barra inicial no padrão.

Terceiro teste:

# .gitignore
dir/*

# git status
Untracked files:
    src/

Isso é consistente com o caso número 2: o padrão tem uma barra dentro dele, por isso é considerado um nome de caminho a partir do diretório raiz.

Agora é a hora da pergunta real. Vamos considerar este arquivo gitignore : quando eles ignoram o diretório downloader/, por exemplo, eles não estão realmente ignorando todos os downloaderdiretórios encontrados em toda a árvore de diretórios? Isso é o que sou levado a pensar desde o que vi sobre o funcionamento do Git antes.

Portanto, se acontecer de eu ter um módulo personalizado com um downloaderdiretório dentro dele, ele será inesperadamente ignorado, bem como o normal na raiz do Magento? Esta é uma pergunta meio retórica porque na verdade já aconteceu comigo, produzindo um bug muito difícil de encontrar.

Então, no .gitignorearquivo Magento (ao qual estou me referindo apenas como um exemplo, aliás) muitos dos padrões contêm barras, então eles são correspondidos corretamente com os nomes de caminho a partir da raiz, mas existem alguns casos, como downloader/ou errors/aquele , se não me engano, são potencialmente perigosos e provavelmente devem ser alterados para /downloader/e /errors/.

Como uma questão mais geral, devo sempre usar a barra inicial para padrões que não contenham barras (exceto para a barra final) quando eu quiser selecionar um nome de caminho explicitamente começando da raiz, e não usá-lo para padrões que contêm barras, ou devo sempre usa a barra inicial para maior clareza? O que você acha disso?

Obrigado por ler e desculpe pela longa postagem.

swahnee
fonte
8
Ótima pergunta e uma explicação muito boa, também fiquei incomodado com isso e sua pesquisa deixou as coisas claras para mim. Depois de ler isso, eu diria que é uma boa prática sempre iniciar os caminhos com uma barra se eles começarem da raiz, isso torna a intenção mais óbvia.
Martinsos
4
Obrigado :) Concordo com sua nota sobre o uso de barras para tornar as intenções mais explícitas.
swahnee
8
Isso deve fazer parte da documentação .gitignore. Muito mais fácil de entender!
rmorrin
Adoraria ver este ótimo post dividido em seções de perguntas e respostas ...
Barett

Respostas:

25

Só queria fazer um resumo para uma possível referência futura rápida - a barra inicial ancora a correspondência na raiz. Assim, no exemplo abaixo, sem a barra, o curinga também excluiria tudo dentro de foo porque ele pegaria *e se moveria recursivamente para baixo na árvore. No entanto, com /*, ele exclui tudo, exceto a pasta foo e seu conteúdo:

$ cat .gitignore
/*
!/foo
solstício333
fonte
24

Você respondeu inteiramente à sua pergunta. Se você olhar o repositório github / gitignore mais de perto, verá que a maioria dos arquivos usa regras inconsistentes sobre como os padrões são escritos; é muito provável que a maioria tenha sido contribuída por pessoas que não se preocuparam em ler a documentação nem testar as coisas como você fez.

Então, se isso ajudar: você está certo, seja confiante.

Se você encontrar erros em projetos colaborativos como este, não hesite em contribuir com seu conhecimento. Há até mesmo algum precedente se você precisar aumentar ainda mais sua confiança.

tne
fonte