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


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

28 3548

28 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

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

touch .keep

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

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

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

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

прежде всего:

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

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

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

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

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

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

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

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

.подход gitkeep

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

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

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

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

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

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

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

принятие

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

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

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

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

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

The 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. добавить его в индекс с помощью команды водопроводным и пустое дерево ша-1:

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

    введите команду и введите вторую строку. Нажмите введите а то 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

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

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

.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. Много работы на Windows, и я не мог найти эквивалентный простой однострочный, чтобы сделать то же самое там. Некоторые из них были достаточно удачливы, чтобы иметь программа установлен по другим причинам, но назначение 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

и это создает a .файл gitkeep в любом пустым каталогом. Даже на окнах :) Примечание: этот файл сборки требует 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 файл и зафиксировать изменение.

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

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

игнорировать файлы в этом каталоге, вы можете добавить его в корневую .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), если вы хотите отслеживать пустая папка, что мая содержат отслеживаемых файлов в будущем, но будет пуст, вы можете пропущены * С и чека это в. В принципе, весь файл говорит: "Не игнорируйте меня", но в остальном каталог пуст и отслеживается.

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

!.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 файл, вы можете игнорировать целые каталоги. Но бывают случаи, когда наличие папки в репо было бы полезно. Вот отличное решение для выполнения этой необходимости.

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

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

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

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

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

*
!.gitignore

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