Como posso adicionar um diretório vazio a um repository Git?

Como posso adicionar um diretório vazio (que não contém arquivos) a um repository Git?

    Outra maneira de fazer um diretório ficar vazio (no repository) é criar um arquivo .gitignore dentro desse diretório que contém estas quatro linhas:

     # Ignore everything in this directory * # Except this file !.gitignore 

    Então você não precisa fazer o pedido corretamente do jeito que você precisa fazer na solução do m104.

    Isso também dá o benefício de que os arquivos nesse diretório não aparecerão como “não rastreados” quando você fizer um status git.

    Tornando o comentário de @GreenAsJade persistente:

    Eu acho que vale a pena notar que esta solução faz exatamente o que a pergunta pediu, mas talvez não seja o que muitas pessoas que estão olhando para essa questão estarão procurando. Essa solução garante que o diretório permaneça vazio. Diz “Eu realmente nunca quero que os arquivos sejam registrados aqui”. Ao contrário de “Eu não tenho nenhum arquivo para verificar aqui, ainda, mas eu preciso do diretório aqui, os arquivos podem vir mais tarde”.

    Você não pode. Veja o FAQ do Git .

    Atualmente, o design do índice git (área de preparação) permite apenas que os arquivos sejam listados, e ninguém competente o suficiente para fazer a alteração para permitir diretórios vazios se preocupou o suficiente com essa situação para remediá-la.

    Os diretórios são adicionados automaticamente ao adicionar arquivos dentro deles. Ou seja, os diretórios nunca precisam ser adicionados ao repository e não são rastreados por conta própria.

    Você pode dizer ” git add

    ” e ele adicionará arquivos lá.

    Se você realmente precisa de um diretório para existir nos checkouts, você deve criar um arquivo nele. .gitignore funciona bem para esse propósito; você pode deixá-lo vazio ou preencher os nomes dos arquivos que você espera que apareçam no diretório.

    Crie um arquivo vazio chamado .gitkeep no diretório e adicione-o.

    Você poderia sempre colocar um arquivo README no diretório com uma explicação de porque você deseja que este diretório, caso contrário vazio, no repository.

     touch .keep 

    No Linux, isso cria um arquivo vazio chamado .keep . Esse nome é preferido em relação ao .gitkeep pois o primeiro é agnóstico ao Git, enquanto o segundo é específico do Git. Em segundo lugar, como outro usuário notou, a convenção de prefixo .git deve ser reservada para arquivos e diretórios que o próprio Git usa.

    Como alternativa, conforme observado em outra resposta , o diretório pode conter um arquivo README ou README.md descritivo.

    Claro que isso requer que a presença do arquivo não cause a quebra do seu aplicativo.

    Por que precisamos de pastas com versões vazias

    Primeiras coisas primeiro:

    Um diretório vazio não pode fazer parte de uma tree sob o sistema de versões do Git .

    Simplesmente não será rastreado. Mas há cenários em que o “versionamento” de um diretório vazio pode ser útil, por exemplo:

    • criar uma estrutura de pastas predefinida para pastas de projetos úteis e disponibilizar essa estrutura para todos os usuários / colaboradores do repository; ou, como um caso especializado do acima, criando uma pasta para arquivos temporários , como um cache/ ou logs/ diretórios
    • alguns projetos simplesmente não funcionarão sem algumas pastas (o que geralmente é um indício de um projeto mal projetado, mas é um cenário frequente do mundo real e talvez possa haver, digamos, problemas de permissão).

    Algumas soluções sugeridas

    Muitos usuários sugerem:

    1. Colocar um arquivo README ou outro arquivo com algum conteúdo para tornar o diretório não vazio ou
    2. Criando um arquivo .gitignore com uma espécie de “lógica reversa” (ou seja, para include todos os arquivos) que, no final, serve o mesmo propósito da abordagem # 1.

    Embora ambas as soluções certamente funcionem , acho que elas são inconsistentes com uma abordagem significativa para o versionamento do Git.

    • Por que você deveria colocar arquivos falsos ou READMEs que talvez você realmente não queira em seu projeto?
    • Por que usar o .gitignore para fazer uma coisa ( manter arquivos) que é exatamente o oposto do que ele significa ( excluindo arquivos), mesmo que seja possível?

    abordagem .gitkeep

    Use um arquivo vazio chamado .gitkeep para forçar a presença da pasta no sistema de version control.

    Embora possa parecer não uma diferença tão grande:

    • Você usa um arquivo com o único propósito de manter a pasta. Você não coloca nenhuma informação que não queira colocar.

      Por exemplo, você deve usar os READMEs como, bem, os READMEs com informações úteis, não como uma desculpa para manter a pasta.

      Separação de preocupações é sempre uma coisa boa, e você ainda pode adicionar um .gitignore para ignorar arquivos indesejados.

    • Nomeando isto .gitkeep faz isto muito claro e direto do próprio nome do arquivo (e também para outros desenvolvedores que são bons para um projeto compartilhado e um das finalidades principais de um repository de Git) que este arquivo é

      • Um arquivo não relacionado ao código (por causa do ponto principal e do nome)
      • Um arquivo claramente relacionado ao Git
      • Sua finalidade ( manter ) é claramente declarada e consistente e semanticamente oposta em seu significado de ignorar

    Adoção

    Eu vi a abordagem do .gitkeep adotada por frameworks muito importantes como o Laravel , o Angular-CLI .

    Conforme descrito em outras respostas, o Git não consegue representar diretórios vazios em sua área de preparação. (Veja a FAQ do Git .) No entanto, se, para seus propósitos, um diretório estiver vazio o suficiente se contiver apenas um arquivo .gitignore , você poderá criar arquivos .gitignore em diretórios vazios somente via:

     find . -type d -empty -exec touch {}/.gitignore \; 

    Andy Lester está certo, mas se o seu diretório só precisa estar vazio, e não vazio vazio, você pode colocar um arquivo .gitignore vazio lá como uma solução alternativa.

    Como um aparte, este é um problema de implementação, não um problema fundamental de design de armazenamento Git. Como já foi mencionado várias vezes na lista de discussão do Git, a razão pela qual isso não foi implementado é que ninguém se importou o suficiente para enviar um patch para ele, não que ele não pudesse ou não devesse ser feito.

    O caminho do Ruby on Rails :

     mkdir log && touch log/.gitkeep && git add log/.gitkeep 

    Agora o diretório de log será incluído na tree. É super-útil ao implementar, assim você não terá que escrever uma rotina para criar diretórios de log.

    Os arquivos de log podem ser mantidos emitindo,

     echo log/dev.log >> .gitignore 

    Mas tu provavelmente sabias disso.

    O Git não rastreia diretórios vazios. Veja o Git FAQ para mais explicações. A solução sugerida é colocar um arquivo .gitignore no diretório vazio. Eu não gosto dessa solução, porque o .gitignore é “escondido” pela convenção Unix. Também não há explicação porque os diretórios estão vazios.

    Eu sugiro colocar um arquivo README no diretório vazio explicando porque o diretório está vazio e porque ele precisa ser rastreado no Git. Com o arquivo README no lugar, no que diz respeito ao Git, o diretório não está mais vazio.

    A verdadeira questão é por que você precisa do diretório vazio no git? Geralmente você tem algum tipo de script de construção que pode criar o diretório vazio antes de compilar / executar. Se não, então faça um. Essa é uma solução muito melhor do que colocar diretórios vazios no git.

    Então você tem alguma razão pela qual você precisa de um diretório vazio no git. Coloque esse motivo no arquivo README. Dessa forma, outros desenvolvedores (e futuros você) sabem por que o diretório vazio precisa estar lá. Você também saberá que pode remover o diretório vazio quando o problema que requer o diretório vazio tiver sido resolvido.


    Para listar todos os diretórios vazios, use o seguinte comando:

     find -name .git -prune -o -type d -empty -print 

    Para criar READMEs de espaço reservado em todos os diretórios vazios:

     find -name .git -prune -o -type d -empty -exec sh -c \ "echo this directory needs to be empty because reasons > {}/README.emptydir" \; 

    Para ignorar tudo no diretório, exceto o arquivo README, coloque as seguintes linhas no seu .gitignore :

     path/to/emptydir/* !path/to/emptydir/README.emptydir path/to/otheremptydir/* !path/to/otheremptydir/README.emptydir 

    Alternativamente, você poderia simplesmente excluir todos os arquivos README de serem ignorados:

     path/to/emptydir/* path/to/otheremptydir/* !README.emptydir 

    Para listar todos os README depois que eles já foram criados:

     find -name README.emptydir 

    AVISO: Esse ajuste não está realmente funcionando como se vê. Desculpe pela inconveniência.

    Post original abaixo:

    Eu encontrei uma solução enquanto brincava com os internos do Git!

    1. Suponha que você esteja no seu repository.
    2. Crie seu diretório vazio:

       $ mkdir path/to/empty-folder 
    3. Adicione-o ao índice usando um comando de encanamento e a tree vazia SHA-1 :

       $ git update-index --index-info 040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 path/to/empty-folder 

      Digite o comando e, em seguida, insira a segunda linha. Pressione Enter e, em seguida, Ctrl + D para finalizar sua input. Nota: o formato é modo [SPACE] tipo [ESPAÇO] SHA-1hash [TAB] caminho (a guia é importante, a formatação de resposta não preserva isso).

    4. É isso aí! Sua pasta vazia está no seu índice. Tudo o que você precisa fazer é se comprometer.

    Esta solução é curta e aparentemente funciona bem ( veja o EDIT! ), Mas não é assim tão fácil de lembrar …

    A tree vazia SHA-1 pode ser encontrada criando um novo repository Git vazio, cd dentro dela e emitindo git write-tree , que produz a tree vazia SHA-1.

    EDITAR:

    Eu tenho usado essa solução desde que a encontrei. Parece funcionar exatamente da mesma maneira que criar um submódulo, exceto que nenhum módulo é definido em lugar algum. Isto leva a erros ao emitir o git submodule init|update . O problema é que git update-index reescreve a parte da 040000 tree em 160000 commit .

    Além disso, qualquer arquivo colocado sob esse caminho nunca será percebido pelo Git, pois ele acha que pertence a algum outro repository. Isso é desagradável, pois pode ser facilmente esquecido!

    No entanto, se você ainda não usa (e não) usa qualquer submódulo do Git em seu repository, e a pasta “vazia” permanecerá vazia ou se você quiser que o Git saiba de sua existência e ignore seu conteúdo, você pode ir com esse ajuste. Indo da maneira usual com submódulos leva mais passos que esse ajuste.

    Talvez adicionar um diretório vazio pareça que seria o caminho de menor resistência porque você tem scripts que esperam que o diretório exista (talvez porque seja um destino para binários gerados). Outra abordagem seria modificar seus scripts para criar o diretório conforme necessário .

     mkdir --parents .generated/bin ## create a folder for storing generated binaries mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed 

    Neste exemplo, você pode verificar em um link simbólico (quebrado) para o diretório para que você possa acessá-lo sem o prefixo “.generated” (mas isso é opcional).

     ln -sf .generated/bin bin git add bin 

    Quando você quiser limpar sua tree de fonts, você pode simplesmente:

     rm -rf .generated ## this should be in a "clean" script or in a makefile 

    Se você adotar a abordagem frequentemente sugerida de fazer check-in em uma pasta quase vazia, terá a menor complexidade de excluir o conteúdo sem excluir o arquivo “.gitignore”.

    Você pode ignorar todos os seus arquivos gerados adicionando o seguinte à sua raiz .gitignore:

     .generated 

    Vamos dizer que você precisa de um diretório vazio chamado tmp :

     $ mkdir tmp $ touch tmp/.gitignore $ git add tmp $ echo '*' > tmp/.gitignore $ git commit -m 'Empty directory' tmp 

    Em outras palavras, você precisa adicionar o arquivo .gitignore ao índice antes de poder dizer ao Git para ignorá-lo (e tudo mais no diretório vazio).

    Eu tenho enfrentado o problema com diretórios vazios também. O problema com o uso de arquivos de espaço reservado é que você precisa criá-los e excluí-los, se eles não forem mais necessários (porque mais tarde foram adicionados subdiretórios ou arquivos. Com grandes trees de origem gerenciando esses arquivos de espaço reservado podem ser incômodos e erro propenso.

    É por isso que decidi escrever uma ferramenta de código aberto que possa gerenciar a criação / exclusão desses arquivos de espaço reservado automaticamente. Ele é escrito para a plataforma .NET e é executado em Mono (.NET para Linux) e Windows.

    Basta dar uma olhada em: http://code.google.com/p/markemptydirs

    Você não pode e, infelizmente, nunca será capaz. Esta é uma decisão tomada pelo próprio Linus Torvald. Ele sabe o que é bom para nós.

    Há um desabafo lá fora em algum lugar que eu li uma vez.

    Eu encontrei Re: diretórios vazios .. , mas talvez haja outro.

    Você tem que viver com as soluções … infelizmente.

    Quando você adiciona um arquivo .gitignore , se você vai colocar qualquer quantidade de conteúdo (que você deseja que o Git ignore) você pode querer adicionar uma única linha com apenas um asterisco * para ter certeza de não adicionar o arquivo. conteúdo ignorado acidentalmente.

    Eu gosto das respostas de @ Artur79 e @mjs então eu tenho usado uma combinação de ambos e o tornei um padrão para nossos projetos.

     find . -type d -empty -exec touch {}/.gitkeep \; 

    No entanto, apenas alguns de nossos desenvolvedores trabalham com Mac ou Linux. Muito trabalho no Windows e eu não consegui encontrar um one-liner simples equivalente para realizar o mesmo lá. Alguns tiveram a sorte de ter o Cygwin instalado por outras razões, mas prescrever o Cygwin apenas por isso pareceu um exagero.

    Então, como a maioria dos nossos desenvolvedores já tem o Ant instalado, eu montei um arquivo de compilation para fazer isso independentemente da plataforma.

     < ?xml version="1.0" encoding="ISO-8859-1"?>                                  

    Agora eu posso simplesmente correr

     ant -f gitkeep.xml 

    E isso cria um arquivo .gitkeep em qualquer subdiretório vazio. Mesmo no Windows 🙂 Nota: Esse arquivo de compilation requer o jar do Ant Contrib .

    Eu continuo trabalhando neste conceito aqui .

    https://github.com/mig82/gitkeep

    As mentioned it’s not possible to add empty directories, but here is a one liner that adds empty .gitignore files to all directories.

    ruby -e 'require "fileutils" ; Dir.glob(["target_directory","target_directory/**"]).each { |f| FileUtils.touch(File.join(f, ".gitignore")) if File.directory?(f) }'

    I have stuck this in a Rakefile for easy access.

    I always build a function to check for my desired folder structure and build it for me within the project. This gets around this problem as the empty folders are held in Git by proxy.

     function check_page_custom_folder_structure () { if (!is_dir(TEMPLATEPATH."/page-customs")) mkdir(TEMPLATEPATH."/page-customs"); if (!is_dir(TEMPLATEPATH."/page-customs/css")) mkdir(TEMPLATEPATH."/page-customs/css"); if (!is_dir(TEMPLATEPATH."/page-customs/js")) mkdir(TEMPLATEPATH."/page-customs/js"); } 

    This is in PHP, but I am sure most languages support the same functionality, and because the creation of the folders is taken care of by the application, the folders will always be there.

    Here is a hack, but it’s funny that it works (Git 2.2.1). Similar to what @Teka suggested, but easier to remember:

    • Add a submodule to any repository ( git submodule add path_to_repo )
    • This will add a folder and a file .submodules . Commit a change.
    • Delete .submodules file and commit the change.

    Now, you have a directory that gets created when commit is checked out. An interesting thing though is that if you look at the content of tree object of this file you’ll get:

    fatal: Not a valid object name b64338b90b4209263b50244d18278c0999867193

    I wouldn’t encourage to use it though since it may stop working in the future versions of Git. Which may leave your repository corrupted.

    There’s no way to get Git to track directories, so the only solution is to add a placeholder file within the directory that you want Git to track.

    The file can be named and contain anything you want, but most people use an empty file named .gitkeep (although some people prefer the VCS-agnostic .keep ).

    The prefixed . marks it as a hidden file.

    Another idea would be to add a README file explaining what the directory will be used for.

    The solution of Jamie Flournoy works great. Here is a bit enhanced version to keep the .htaccess :

     # Ignore everything in this directory * # Except this file !.gitignore !.htaccess 

    With this solution you are able to commit a empty folder, for example /log , /tmp or /cache and the folder will stay empty.

    Você não pode. This is an intentional design decision by the Git maintainers. Basically, the purpose of a Source Code Management System like Git is managing source code and empty directories aren’t source code. Git is also often described as a content tracker, and again, empty directories aren’t content (quite the opposite, actually), so they are not tracked.

    Sometimes you have to deal with bad written libraries or software, which need a “real” empty and existing directory. Putting a simple .gitignore or .keep might break them and cause a bug. The following might help in these cases, but no guarantee…

    First create the needed directory:

     mkdir empty 

    Then you add a broken symbolic link to this directory (but on any other case than the described use case above, please use a README with an explanation):

     ln -s .this.directory empty/.keep 

    To ignore files in this directory, you can add it in your root .gitignore :

     echo "/empty" >> .gitignore 

    To add the ignored file, use a parameter to force it:

     git add -f empty/.keep 

    After the commit you have a broken symbolic link in your index and git creates the directory. The broken link has some advantages, since it is no regular file and points to no regular file. So it even fits to the part of the question “(that contains no files)”, not by the intention but by the meaning, I guess:

     find empty -type f 

    This commands shows an empty result, since no files are present in this directory. So most applications, which get all files in a directory usually do not see this link, at least if they do a “file exists” or a “is readable”. Even some scripts will not find any files there:

     $ php -r "var_export(glob('empty/.*'));" array ( 0 => 'empty/.', 1 => 'empty/..', ) 

    But I strongly recommend to use this solution only in special circumstances, a good written README in an empty directory is usually a better solution. (And I do not know if this works with a windows filesystem…)

    Adding one more option to the fray.

    Assuming you would like to add a directory to git that, for all purposes related to git , should remain empty and never have it’s contents tracked, a .gitignore as suggested numerous times here, will do the trick.

    The format, as mentioned, is:

     * !.gitignore 

    Now, if you want a way to do this at the command line, in one fell swoop, while inside the directory you want to add, you can execute:

     $ echo "*" > .gitignore && echo '!.gitignore' >> .gitignore && git add .gitignore 

    Myself, I have a shell script that I use to do this. Name the script whatever you whish, and either add it somewhere in your include path, or reference it directly:

     #!/bin/bash dir='' if [ "$1" != "" ]; then dir="$1/" fi echo "*" > $dir.gitignore && \ echo '!.gitignore' >> $dir.gitignore && \ git add $dir.gitignore 

    With this, you can either execute it from within the directory you wish to add, or reference the directory as it’s first and only parameter:

     $ ignore_dir ./some/directory 

    Another option (in response to a comment by @GreenAsJade), if you want to track an empty folder that MAY contain tracked files in the future, but will be empty for now, you can ommit the * from the .gitignore file, and check that in. Basically, all the file is saying is “do not ignore me “, but otherwise, the directory is empty and tracked.

    Your .gitignore file would look like:

     !.gitignore 

    That’s it, check that in, and you have an empty, yet tracked, directory that you can track files in at some later time.

    The reason I suggest keeping that one line in the file is that it gives the .gitignore purpose. Otherwise, some one down the line may think to remove it. It may help if you place a comment above the line.

    If you want to add a folder that will house a lot of transient data in multiple semantic directories, then one approach is to add something like this to your root .gitignore…

    /app/data/**/*.* !/app/data/**/*.md

    Then you can commit descriptive README.md files (or blank files, doesn’t matter, as long as you can target them uniquely like with the *.md in this case) in each directory to ensure that the directories all remain part of the repo but the files (with extensions) are kept ignored. LIMITATION: . ‘s are not allowed in the directory names!

    You can fill up all of these directories with xml/images files or whatever and add more directories under /app/data/ over time as the storage needs for your app develop (with the README.md files serving to burn in a description of what each storage directory is for exactly).

    There is no need to further alter your .gitignore or decentralise by creating a new .gitignore for each new directory. Probably not the smartest solution but is terse gitignore-wise and always works for me. Nice and simple! 😉

    insira a descrição da imagem aqui

    You can save this code as create_readme.php and run the PHP code from the root directory of your Git project.

     > php create_readme.php 

    It will add README files to all directories that are empty so those directories would be then added to the index.

     < ?php $path = realpath('.'); $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); foreach($objects as $name => $object){ if ( is_dir($name) && ! is_empty_folder($name) ){ echo "$name\n" ; exec("touch ".$name."/"."README"); } } function is_empty_folder($folder) { $files = opendir($folder); while ($file = readdir($files)) { if ($file != '.' && $file != '..') return true; // Not empty } } ?> 

    Then do

     git commit -m "message" git push 

    Sometimes I have repositories with folders that will only ever contain files considered to be “content”—that is, they are not files that I care about being versioned, and therefore should never be committed. With Git’s .gitignore file, you can ignore entire directories. But there are times when having the folder in the repo would be beneficial. Here’s a excellent solution for accomplishing this need.

    What I’ve done in the past is put a .gitignore file at the root of my repo, and then exclude the folder, like so:

     /app/some-folder-to-exclude /another-folder-to-exclude/* 

    However, these folders then don’t become part of the repo. You could add something like a README file in there. But then you have to tell your application not to worry about processing any README files.

    If your app depends on the folders being there (though empty), you can simply add a .gitignore file to the folder in question, and use it to accomplish two goals:

    Tell Git there’s a file in the folder, which makes Git add it to the repo. Tell Git to ignore the contents of this folder, minus this file itself. Here is the .gitignore file to put inside your empty directories:

     * !.gitignore 

    The first line (*) tells Git to ignore everything in this directory. The second line tells Git not to ignore the .gitignore file. You can stuff this file into every empty folder you want added to the repository.