Как добавить пустой каталог в репозиторий Git?

Как добавить пустой каталог (который не содержит файлов) в репозиторий Git?

28 ответов


другой способ сделать каталог пустым (в репозитории) - создать .gitignore файл внутри этого каталога, который содержит эти четыре строки:

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

тогда вам не нужно получать заказ правильно, как это нужно делать в M104 решение.

Это также дает преимущество, что файлы в этом каталоге не будут отображаться как "untracked" при выполнении статуса git.

делая @GreenAsJadeкомментарий настойчивый:

Я думаю, стоит отметить, что это решение делает именно то, что задан вопрос, но, возможно, не то, что многие люди, глядя на этот вопрос, будут искать. Это решение гарантирует, что каталог останется пустым. Он говорит: "Я действительно никогда не хочу, чтобы файлы проверялись здесь". В отличие от "у меня нет файлов для регистрации здесь, но мне нужен каталог здесь, файлы могут появиться позже".


вы не можете. Вижу git FAQ.

В настоящее время дизайн индекса git (промежуточная область) разрешает только файлы быть перечисленным, и никто достаточно компетентный чтобы внести изменения, чтобы разрешить пустой каталоги достаточно заботились о эту ситуацию исправить.

каталоги добавляются автоматически при добавлении файлов внутри них. Что есть каталоги не должны быть добавлены в репозиторий и не отслеживаются на их собственный.

вы можете сказать:"git add <dir>" и добавлю туда файлы.

Если вам действительно нужен каталог для exist in checkouts вы должны создать файлы в ней. .пример хорошо работает для эта цель; вы можете оставить ее пустой, или заполнять имена файлов ожидайте появления в каталоге.


создайте пустой файл с именем .gitkeep в каталоге и добавьте это.


вы всегда можете поместить файл README в каталог с объяснением, почему вы хотите, чтобы этот, в противном случае пустой, каталог в репозитории.


touch .keep

в Linux это создает пустой файл с именем .keep. Это имя предпочтительнее .gitkeep поскольку первый агностик для Git, тогда как последний специфичен для Git. Во-вторых, как отметил другой пользователь,.git соглашение префикса должно быть зарезервировано для файлов и каталогов, которые использует сам Git.

альтернативно, как отмечено в другом ответ каталог может содержать описательные README или вместо.

конечно, это требует, чтобы наличие файла не приведет к разрыву вашего приложения.


зачем нам нужны пустые версионной папки

перво-наперво:

пустой каталог не может быть частью дерева в системе управления версиями Git.

он просто не будет отслеживаться. Но есть сценарии, в которых" управление версиями " пустой каталог может быть полезным, например:

  • строительство предопределенная структура папок для полезных папок проекта и сделайте это структура, доступная каждому пользователю / участнику репозитория; или, как специализированный случай выше, Создание папки для временные файлы, например,cache/ или logs/ каталоги
  • некоторые проекты просто не будет работать без некоторых папок (что часто является намеком на плохо разработанный проект, но это частый реальный сценарий, и, возможно, могут быть, скажем, проблемы с разрешением).

некоторые предлагали обходные пути

многие пользователи предполагают:

  1. размещение README файл или другой файл с некоторым содержимым, чтобы сделать каталог непустым, или
  2. создание .gitignore файл с своего рода" обратной логикой " (т. е. включать все файлы), которая, в конце концов, служит той же цели подхода № 1.

пока оба решения, безусловно, работают я нахожу их unconsistent с осмысленным подходом к Git управление версиями.

  • почему вы должны поместить поддельные файлы или READMEs, которые, возможно, вы действительно не хотите в своем проекте?
  • зачем использовать .gitignore сделать (содержание файлы), что является полной противоположностью тому, что он предназначен для (кроме файлы), хотя это возможно?

.подход gitkeep

использовать пустой под названием .gitkeep для того, чтобы заставить наличии папка в системе управления версиями.

хотя это может показаться не такой уж большой разницы:

  • вы используете файл с один цель хранения папки. Вы не кладете туда информацию, которую не хотите класть.

    например, вы должны использовать READMEs как, ну, READMEs с полезной информацией, а не как предлог, чтобы сохранить папку.

    разделение проблем всегда хорошо, и вы все еще можете добавить а .gitignore игнорировать ненужные файлы.

  • назвав его .gitkeep делает его очень ясным и понятным из самого имени файла (а также другим разработчикам, что хорошо для общего проекта и одной из основных целей репозитория Git) , что этот файл

    • файл, не связанный с кодом (из-за ведущей точки и имени)
    • файл, явно связанный с Git
    • его цель ( keep) четко сформулирован и последователен и семантически противопоставлен по своему значению игнорировать

принятие

Я видел .gitkeep подход, принятый очень важными рамками, такими как что Laravel, угловой-CLI.


как описано в других ответах, Git не может представлять пустые каталоги в своей промежуточной области. (См. git FAQ.) Однако, если для ваших целей каталог достаточно пуст, если он содержит .gitignore только файл, затем вы можете создать .gitignore файлы в пустых каталогах только через:

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

Энди Лестер прав, но если ваш каталог должен быть пустым, а не пустой пуст, вы можете поставить пустой там в качестве обходного пути.

в стороне, это проблема реализации, а не фундаментальная проблема дизайна хранилища Git. Как упоминалось много раз в списке рассылки Git, причина, по которой это не было реализовано, заключается в том, что никто не позаботился о том, чтобы отправить патч для него, а не в том, что это не могло или не должно быть сделано.


на Ruby на Rails путь:

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

теперь каталог журнала будет включен в дерево. Это очень полезно при развертывании, поэтому вам не придется писать процедуру для создания каталогов журналов.

лог-файлов может быть командой,

echo log/dev.log >> .gitignore

но вы, вероятно, знали это.


Git не отслеживает пустые каталоги. Вижу git FAQ для получения дополнительных объяснений. Предлагаемое обходное решение-поставить .gitignore файл в пустом каталоге. Мне не нравится это решение, потому что .gitignore "скрыто" конвенцией Unix. Также нет объяснения, почему каталоги пустые.

Я предлагаю поместить файл README в пустой каталог, объясняя, почему каталог пуст и почему его нужно отслеживать в Git. С файлом README в место, насколько это касается Git, каталог больше не пуст.

реальный вопрос в том, зачем вам нужен пустой каталог в git? Обычно у вас есть какой-то скрипт сборки, который может создать пустой каталог перед компиляцией/запуском. Если нет, то сделайте один. Это гораздо лучшее решение, чем помещать пустые каталоги в git.

Итак, у вас есть причина, по которой вам нужен пустой каталог в git. Поместите эту причину в файл README. Таким образом другие разработчики (и будущие вы) знаете, почему пустой каталог должен быть там. Вы также будете знать, что вы можете удалить пустой каталог, когда проблема, требующая пустой каталог был решен.


чтобы перечислить каждый пустой каталог, используйте следующую команду:

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

чтобы создать READMEs заполнителя в каждом пустом каталоге:

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

чтобы игнорировать все в каталоге, кроме файла README, поместите следующие строки в свой .gitignore:

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

кроме того, вы можете просто исключить файл README от игнорирования:

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

чтобы перечислить каждый README после того, как они уже созданы:

find -name README.emptydir

предупреждение: Эта настройка действительно не работает, как оказалось. извините за неудобства.

Оригинальный пост ниже:

я нашел решение во время игры с Git internals!

  1. Предположим, вы находитесь в своем репозитории.
  2. создайте свой пустой каталог:

    $ mkdir path/to/empty-folder
    
  3. добавьте его в индекс с помощью команды plumbing и пустого дерева ша-1:

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

    введите команду и введите вторую строку. Нажмите Enter а то Ctrl + D для завершения ввода. Примечание: формат режим [пробел] тип [пробел] SHA-1hash [TAB] путь (вкладка важна, форматирование ответа не сохраняет ее).

  4. вот именно! Ваши пустые папки в индекс. Все, что тебе нужно. сделать-значит совершить.

это решение короткое и, по-видимому, работает нормально (см. редактирование!), но это не так легко запомнить...

пустое дерево SHA-1 можно найти, создав новый пустой репозиторий Git,cd в этом и проблема git write-tree, который выводит пустое дерево SHA-1.

EDIT:

я использую это решение с тех пор, как нашел его. Похоже, это работает точно так же, как создание подмодуль, за исключением того, что модуль нигде не определен. Это приводит к ошибкам при выдаче git submodule init|update. Проблема в том, что git update-index заменить 040000 tree на 160000 commit.

более того, любой файл, помещенный под этот путь, никогда не будет замечен Git, поскольку он думает, что они принадлежат к какому-то другому репозиторию. Это противно, так как это можно легко пропустить!

однако, если вы еще не используете (и не будете) использовать какие-либо подмодули Git в своем репозитории, и" пустая " папка останется пустой или если вы хотите, чтобы Git знал о его существовании и игнорировал его содержимое, вы можете пойти с этой настройкой. Идя обычным путем с подмодулями, делает больше шагов, чем эта настройка.


возможно, добавление пустого каталога кажется, что это будет путь наименьшего сопротивления потому что у вас есть скрипты, которые ожидают, что этот каталог будет существовать (возможно, потому, что он является целью для сгенерированных двоичных файлов). Другой подход -измените свои скрипты, чтобы создать каталог по мере необходимости.

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

в этом примере вы можете проверить (сломанную) символическую ссылку на каталог, чтобы получить к нему доступ без ".сгенерированный " префикс (но это необязательно).

ln -sf .generated/bin bin
git add bin

когда вы хотите очистить свое дерево источника, вы можете просто:

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

если вы берете часто предлагаемый подход проверки в почти пустой папке, у вас есть небольшая сложность удаления содержимого без удаления".gitignore " file.

вы можете игнорировать все ваши сгенерированные файлы, добавив следующее в свой корень .пример:

.generated

предположим, вам нужен пустой каталог с именем tmp :

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

другими словами, вам нужно добавить .gitignore файл в индекс, прежде чем вы можете сказать Git игнорировать его (и все остальное в пустом каталоге).


Я тоже столкнулся с проблемой с пустыми каталогами. Проблема с использованием файлов-заполнителей заключается в том, что вам нужно создать их и удалить, если они больше не нужны (потому что позже были добавлены подкаталоги или файлы. С большими исходными деревьями управление этими файлами заполнителей может быть громоздким и подверженным ошибкам.

вот почему я решил написать инструмент с открытым исходным кодом, который может управлять созданием/удалением таких файлов-заполнителей автоматически. Это написано для платформы .NET и работает под Mono (.NET для Linux) и Windows.

просто взгляните на:http://code.google.com/p/markemptydirs


вы не можете и, к сожалению, никогда не сможете. Это решение принял сам Линус Торвальд. Он знает, что для нас хорошо.

где-то там есть разглагольствования, которые я когда-то читал.

нашел Re: пустые каталоги.., но, может быть, есть еще один.

вы должны жить с обходными путями...к сожалению.


при добавлении .gitignore файл, если вы собираетесь поместить в него любое количество контента (которое вы хотите игнорировать Git), вы можете добавить одну строку со звездочкой * чтобы убедиться, что вы не добавляете игнорируемый контент случайно.


мне нравятся ответы @Artur79 и @mjs, поэтому я использую комбинацию обоих и сделал ее стандартом для наших проектов.

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

однако, только несколько наших разработчиков работают на Mac или Linux. Много работы над окнами, и я не мог найти эквивалентный простой однострочный, чтобы выполнить то же самое там. Некоторым посчастливилось иметь Cygwin установлен по другим причинам, но назначение Cygwin только для этого казалось излишним.

Так, так как большинство у наших разработчиков уже есть АНТ установлен, я собрал файл сборки, чтобы выполнить это независимо от платформы.

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Gitkeep" basedir="." default="keep">
    <!--Apply to all subdirs of this dir-->
    <target name="keep" description="-> Add a .gitkeep file to all empty subdir's of this dir.">

        <!--Create a ref to all the subdirs in the tree of this dir-->
        <dirset id="dirs.ref" dir="./" includes="**/*"/>
        <!--Create a list of the subdirs under this dir-->
        <property name="dirs.list" refid="dirs.ref" />

        <!--For each subdir-->
        <for list="${dirs.list}" delimiter=";" param="dir">
            <sequential>
                <!--If the subdir is empty this target will add a .gitkeep file to it-->
                <antcall target="gitkeep" inheritall="false">
                    <param name="dir" value="@{dir}"/>
                </antcall>
            </sequential>
        </for>
    </target>

    <!--Add a .gitkeep file to a directory if it's empty-->
    <target name="gitkeep" description="-> Add a .gitkeep file to a specific subdir of this dir. Use -Ddir=relative/path/to/dir">

        <!--Create a ref of the files inside this dir-->
        <fileset dir="${dir}" id="contents.ref"/>

        <!--Create a path to the contents of this directory, ONLY if it's not empty-->
        <pathconvert refid="contents.ref" property="contents.path" setonempty="false"/>

        <if>
            <!--If the dir is empty create the .gitkeep file-->
            <not><isset property="contents.path"/></not>
            <then>
                <!--Create the .gitkeep file-->
                <echo message="Version this dir in Git even if its empty." file="./${dir}/.gitkeep" force="true" append="false"/>
            </then>
        </if>
    </target>
</project>

Теперь я могу просто запустить

ant -f gitkeep.xml

и это создает .файл gitkeep в любом пустым каталогом. Даже на Windows :) Примечание: этот файл build требует Ant Contrib jar.

Я продолжаю работать над этой концепцией здесь.

https://github.com/mig82/gitkeep


Как уже упоминалось, невозможно добавить пустые каталоги, но вот одна строка, которая добавляет пустые .файлы gitignore для всех каталогов.

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

я вставил это в Rakefile для легкого доступа.


Я всегда создаю функцию, чтобы проверить желаемую структуру папок и построить ее для меня в проекте. Это обходит эту проблему, поскольку пустые папки хранятся в git по прокси-серверу.

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");
}

это в PHP, но я уверен, что большинство языков поддерживают ту же функциональность, и поскольку создание папок заботится о приложении, папки всегда будут там.


вот хак, но забавно, что он работает (Git 2.2.1). Похоже на то, что предложил @Teka, но легче запомнить:

  • добавить подмодуль в любой репозиторий (git submodule add path_to_repo)
  • добавить папку и файл .submodules. Внесите изменения.
  • удалить .submodules file и зафиксировать изменение.

Теперь у вас есть каталог, который создается при извлечении фиксации. Интересная вещь, хотя, если вы посмотрите на содержание объект дерева этого файла вы получите:

fatal: недопустимое имя объекта b64338b90b4209263b50244d18278c0999867193

Я бы не рекомендовал использовать его, Хотя, поскольку он может перестать работать в будущих версиях Git. Что может привести к повреждению репозитория.


нет способа заставить git отслеживать каталоги, поэтому единственным решением является добавление файла-заполнителя в каталог, который вы хотите отслеживать Git.

файл может быть назван и содержать все, что вы хотите, но большинство людей используют пустой файл с именем .gitkeep (хотя некоторые люди предпочитают VCS-агностик .keep).

префиксом . помечает его как скрытый файл.

другой идеей было бы добавить README файл, объясняющий, что каталог будет используется для.


решение Джейми Флурной работает отлично. Вот немного расширенная версия, чтобы сохранить .htaccess :

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

С помощью этого решения вы можете зафиксировать пустую папку, например /log, /tmp или /cache и папка останется пустой.


ты не можешь. Это преднамеренное дизайнерское решение сопровождающих Git. В принципе, целью системы управления исходным кодом, такой как Git, является управление исходным кодом, а пустые каталоги не являются исходным кодом. Git также часто описывается как трекер контента, и опять же, пустые каталоги не являются контентом (на самом деле, наоборот), поэтому они не отслеживаются.


иногда вам приходится иметь дело с плохими написанными библиотеками или программным обеспечением, которым нужен "реальный" пустой и существующий каталог. Положить простой .gitignore или .keep может сломать их и привести к ошибке. В этих случаях может помочь следующее, но не гарантия...

сначала создайте необходимый каталог:

mkdir empty

затем вы добавляете сломанную символическую ссылку в этот каталог (но в любом другом случае, кроме описанного выше варианта использования, используйте README С пояснение):

ln -s .this.directory empty/.keep

чтобы игнорировать файлы в этом каталоге, вы можете добавить его в свой root .gitignore:

echo "/empty" >> .gitignore

чтобы добавить игнорируемый файл, используйте параметр, чтобы принудительно его:

git add -f empty/.keep

после фиксации у вас есть сломанная символическая ссылка в вашем индексе, и git создает каталог. Сломанная ссылка имеет некоторые преимущества, так как она не является обычным файлом и не указывает на обычный файл. Таким образом, он даже подходит к части вопроса "(которая не содержит файлов)", а не намерение, но по смыслу, я думаю:

find empty -type f

эта команда показывает пустой результат, так как в этом каталоге нет файлов. Поэтому большинство приложений, которые получают все файлы в каталоге, обычно не видят этой ссылки, по крайней мере, если они делают "файл существует" или "читается". Даже некоторые скрипты не найдут там никаких файлов:

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

но я настоятельно рекомендую использовать это решение только при особых обстоятельствах, хорошо написано README в пустом каталоге обычно это лучшее решение. (И я не знаю, работает ли это с файловой системой windows...)


добавление еще одного варианта в драку.

предполагая, что вы хотите добавить каталог в git, что для всех целей, связанных с git, должен оставаться пустым и никогда не отслеживать его содержимое, a .gitignore как полагают много раз здесь, будет делать трюк.

формат, как уже упоминалось, является:

*
!.gitignore

теперь, если вы хотите способ, чтобы сделать это в командной строке, одним махом, в то время как внутри - каталог вы хотите добавить, вы можете выполнить:

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

у меня есть сценарий оболочки, который я использую для этого. Назовите сценарий, что вы хотите, и либо добавьте его где-нибудь в свой путь включения, либо ссылайтесь на него напрямую:

#!/bin/bash

dir=''

if [ "" != "" ]; then
    dir="/"
fi

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

С этим вы можете либо выполнить его из каталога, который хотите добавить, либо ссылаться на каталог, поскольку это первый и единственный параметр:

$ ignore_dir ./some/directory

другой вариант (в ответ на комментарий @GreenAsJade), если вы хотите отслеживать пустая папка, что мая содержат отслеживаемые файлы в будущем, но будут пустыми на данный момент, Вы можете ommit * С и чека это in. В принципе, весь файл говорит: "Не игнорируйте меня", но в остальном каталог пуст и отслеживается.

код .gitignore файл будет выглядеть так:

!.gitignore

вот и все, проверьте это, и у вас есть пустой, но отслеживаемый каталог, который вы можете отслеживать документы поступят позже.

причина, по которой я предлагаю сохранить эту строку в файле, заключается в том, что она дает .gitignore цель. В противном случае, кто-то вниз по линии может подумать, чтобы удалить его. Это может помочь, если вы разместите комментарий над строкой.


если вы хотите добавить папку, в которой будет много переходных данных в нескольких семантических каталогах, то один подход-добавить что-то вроде этого в свой корень .гитюдного...

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

затем вы можете зафиксировать описательный README.md-файлы (или пустые файлы, не имеет значения, если вы можете нацелить их однозначно, как с *.md в этом случае) в каждом каталоге, чтобы убедиться, что все каталоги остаются частью РЕПО, но файлы (с расширениями) хранятся игнорируется. Ограничение:. ' s не допускаются в именах каталогов!

вы можете заполнить все эти каталоги файлами xml / images или чем угодно и добавить больше каталогов в /app/data/ со временем по мере необходимости хранения для вашего приложения (с помощью README.файлы md, служащие для записи в описании того, для чего именно предназначен каждый каталог хранения).

нет необходимости дополнительно изменять ваш .gitignore или децентрализовать, создав новый .gitignore для каждого нового справочник. Вероятно, не самое умное решение, но краткое gitignore-мудрое и всегда работает для меня. Красиво и просто! ;)

enter image description here


вы можете сохранить этот код как create_readme.php и запустите PHP код из корневого каталога Вашего проекта в Git.

> php create_readme.php

Он добавит файлы README во все пустые каталоги, чтобы эти каталоги затем были добавлены в индекс.

<?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
            }
        }
?>
сделать
git commit -m "message"
git push

иногда у меня есть репозитории с папками, которые будут содержать только файлы, считающиеся "содержимым", то есть они не являются файлами, которые меня волнуют, и поэтому никогда не должны быть зафиксированы. С Git это .файл gitignore, вы можете игнорировать целые каталоги. Но бывают случаи, когда наличие папки в репо было бы полезно. Вот отличное решение для удовлетворения этой потребности.

что я сделал в прошлом кладут .файл гитюдного в корне мое РЕПО, а затем исключить папку, например:

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

однако эти папки затем не становятся частью РЕПО. Вы можете добавить туда что-то вроде файла README. Но тогда вы должны сказать своему приложению не беспокоиться об обработке любых файлов README.

Если ваше приложение зависит от папок есть (хоть и пустые), вы можете просто добавить .gitignore файл в папку, о которой идет речь, и использовать его для достижения двух целей:

скажите Git, что есть файл в папке, которая заставляет Git добавить ее в репо. Сказать git игнорировать содержимое этой папки, минус сам этот файл. Вот .gitignore файл, чтобы поместить в пустые каталоги:

*
!.gitignore

первая строка ( * ) говорит Git игнорировать все в этом каталоге. Вторая строка говорит Git не игнорировать .файла.gitignore Вы можете поместить этот файл в каждую пустую папку, которую хотите добавить в репозиторий.