Listar arquivos não armazenados em repositórios do Git

4

Eu quero descobrir quais arquivos em um determinado diretório não são gerenciados pelo Git. Isto é assim porque eu uso o Git para backups, e eu quero eventualmente colocar todos os meus arquivos lá.

Que ferramenta unix poderia conseguir isso? Existe uma maneira de usar find para fazer isso de uma maneira razoavelmente eficiente?

Exemplo:

Eu tenho uma pasta onde eu armazeno coisas relacionadas a RFC, parece assim:

.
├── TheFile
└── tests
    ├── 4180
    │   └── data
    │       ├── bad
    │       └── good
    │           └── linebreaks.csv
    ├── get-rfc.sh
    ├── .git <contents omited>
    ├── LICENSE
    ├── README
    └── rfc4180.txt

Estou procurando um comando que me mostrará:

TheFile
    
por Willem 15.11.2016 / 15:17

4 respostas

4
find the_starting_dir \( -type d -exec test -d '{}'/.git \; -prune \) -o -print

Não é a mais portável de invocações de localização, mas funciona com o GNU find.

O Find percorre a árvore de diretórios. O termo -prune retorna true, mas interrompe find do processamento posterior da subárvore. Então o lado esquerdo do -o diz "se este é um diretório, e se test diz que existe um subdiretório chamado .git e se prune retorna verdadeiro então terminamos de processar essa coisa no árvore". O lado direito diz "caso contrário, imprima"

Se você não quiser que os diretórios sejam impressos, altere -print para \( ! -type d -print \) , mas você não receberá nenhuma indicação sobre os diretórios vazios.

Você pode alterar -print para -ls para obter listagens, -printf consulte o manual etc etc.

    
por 15.11.2016 / 16:26
1

Eu não entendo porque você não quer usar o git ...

git status --untracked-files

[editar]

As I understand the request, there is a directory tree. Inside this tree there are multiple git repos, but there is not one covering the whole tree. The example shows a git repo in the tests sub directory. Therefore your suggested command would get a git error fatal: Not in a git repository rather than TheFile as requested.

find . -name .git  -exec echo  $(realpath '{}') \; |\
sed 's/\(.*\)\(.git\)/git --git-dir= --work-tree= status --untracked-files/g' | bash  
    
por 16.11.2016 / 20:28
0

Há muitos casos específicos em sua solicitação.

  1. Arquivos realmente fora de um diretório gerenciado pelo git.
    • Seu TheFile se encaixa neste caso.
  2. Arquivos dentro de um diretório gerenciado pelo Git, com algum marcador .git . .git nem sempre é um diretório. Pode ser um arquivo também, com um caminho para o GIT_DIR real. Podemos quebrar ainda mais esses arquivos da seguinte forma:
    1. Arquivos conhecidos, aqueles presentes no índice do Git.
    2. Arquivos ignorados, aqueles arquivos que correspondem a um padrão por gitignore(5) :
      • .gitignore
      • $HOME/.config/git/ignore
      • $GIT_DIR/info/exclude
    3. Arquivos sob um diretório $GIT_DIR real, mas NÃO parte do repositório.
      • .git/hooks são os mais prováveis
      • Também pode ser malware

Assim, o caso mais confiável, será gerar duas listas, relativas ao seu diretório de base $D , e compará-las (não se esqueça de classificá-las e remover duplicatas de antemão).

Eu não consigo pensar em uma maneira confiável de gerar a sub-lista para 2.3 acima, então deixo isso como um problema em aberto (eu adoraria saber disso, porque eu perdi ganchos antes). / p>

Script de shell para listar arquivos conhecidos por 2.1 acima:

for g in $(find $D -name .git) ; do
  echo $g 
  p=${g%/.git} g2='readlink -f $g' ;
  ( cd $p && GIT_DIR=$g2 \
  git ls-files --exclude-standard --full-name ) \
  | sed "s,^,${p}/,g" ; 
done > list-2.1

Script de shell para listar arquivos ignorados por 2.2 acima:

for g in $(find $D -name .git) ; do
  p=${g%/.git} g2='readlink -f $g' ;
  ( cd $p && GIT_DIR=$g2 \
  git ls-files \
  --others -i --exclude-standard ) \
  | sed "s,^,${p}/,g" ; 
done > list-2.2

Script de shell para listar arquivos por 2.3 acima:

TODO > list-2.3

Script de shell para processar as listas e encontrar o que não está no lado B:

comm -23 <(find $D ! -type d |sort) <(sort 2.1 2.2 2.3 | uniq)
    
por 16.11.2016 / 00:16
-1
find <root_dir> -type d -name ".git"

é isso que você está procurando?

você também pode fazer algo como

find <root_dir> -type d -name ".git" -print0 | xargs -0 -r dirname

para gerar apenas os nomes dos diretórios sem a /.git part; você pode até mesmo evitar dirname e apenas usar a saída de find plus /../ no final de cada nome de pasta.

find <root_dir> -type d -name ".git" -print0 | xargs -0 -r printf "%s/../"

EDITAR

Você pode negar o parâmetro -name e reproduzir com o valor -maxdepth ; Por exemplo, posso listar facilmente todos os diretórios na minha árvore de kernel que não têm um nome que comece com c (maiúscula ou minúscula).

find linux-4.8.2/ -type d ! -iname "c*" -maxdepth 1

Eu ainda não entendi o que você quer dizer com:

I'm looking for the exact opposite of this, namely a command which find all files not in a Git repo;

simplesmente porque os arquivos que estão no mesmo diretório no mesmo sistema de arquivos do diretório raiz .git podem nem ser parte de um repositório, isso significa que literalmente existem arquivos no mesmo diretório (ou subdiretórios) ) onde existe um diretório chamado .git também. Lembre-se que git tem o conceito de staging e, em geral, o que você vê em um disco pode não ser o seu repositório git.

Dê uma olhada no link que é o C lib oficial do git e há muitas ligações para ele, além de muitas docs, exemplos e como.

    
por 15.11.2016 / 15:48