Вопрос по git-add, directory, git – Как я могу добавить пустой каталог в Git-репозиторий?

3718

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

Почему бы не создать процедуру, которая создает файлы tmp, и создать каталог tmp? RyPeck
Хотя это бесполезно,there is a way to hack an empty (really empty) directory into your repo, Это не будетcheckout с текущими версиями Git, однако. tiwo
@AdamMarshall Я думаю, что tiwo говорил, что взлом не является полезным, так как он игнорируется при оформлении заказа. Директории Tmp звучат как полезная функция для VCS. Quantum7
@ Я не согласен с тем, что это бесполезно. Ваша иерархия каталогов является частью вашего проекта, поэтому она должна контролироваться версией. JBentley
В моем случае я хотел бы добавить структуру каталогов для файлов tmp, но не сами файлы tmp. Благодаря этому мой тестер имеет правильную структуру (в противном случае возникают ошибки), но я не забиваю свои коммиты данными tmp. Так что да, это полезно для меня! Adam Marshall

Ваш Ответ

28   ответов
638

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

Это не так. Дело в том, что это может сбить с толку.
В этом случаеREADME или жеABOUT файл будет так же хорошо или лучше. Оставить записку для следующего парня, как мы все делали до URL.
Я добавилanswer поощряя создавать.keep вместо.
@ t-mart & quot;.git Соглашение префикса должно быть зарезервировано ... & quot; Зачем? Git запрашивает это бронирование?
.gitkeep не было предписано Git и заставит людей вторично угадать его значение, что приведет их к поискам в Google, которые приведут их сюда..git Соглашение префикса должно быть зарезервировано для файлов и каталогов, которые использует сам Git.
245
Why would we need empty versioned folders

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

An empty directory cannot be part of a tree under the Git versioning system.

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

scaffolding a predefined folder structure, making it available to every user/contributor of the repository; or, as a specialized case of the above, creating a folder for temporary files, such as a cache/ or logs/ directories, where we want to provide the folder but .gitignore its contents related to the above, some projects won't work without some folders (which is often a hint of a poorly designed project, but it's a frequent real-world scenario and maybe there could be, say, permission problems to be addressed). Some suggested workarounds

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

Placing a README file or another file with some content in order to make the directory non-empty, or Creating a .gitignore file with a sort of "reverse logic" (i.e. to include all the files) which, at the end, serves the same purpose of approach #1.

В то время какboth solutions surely work Я нахожу их несовместимыми с осмысленным подходом к Git-версиям.

Why are you supposed to put bogus files or READMEs that maybe you don't really want in your project? Why use .gitignore to do a thing (keeping files) that is the very opposite of what it's meant for (excluding files), even though it is possible? .gitkeep approach

Используйтеempty файл называется.gitkeep для принудительного присутствия папки в системе управления версиями.

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

You use a file that has the single purpose of keeping the folder. You don't put there any info you don't want to put.

For instance, you should use READMEs as, well, READMEs with useful information, not as an excuse to keep the folder.

Separation of concerns is always a good thing, and you can still add a .gitignore to ignore unwanted files.

Naming it .gitkeep makes it very clear and straightforward from the filename itself (and also to other developers, which is good for a shared project and one of the core purposes of a Git repository) that this file is

A file unrelated to the code (because of the leading dot and the name) A file clearly related to Git Its purpose (keep) is clearly stated and consistent and semantically opposed in its meaning to ignore Adoption

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

downvote: подробный ответ.
@RomanAllenstein: не обязательно. Возможно, вы создадите репо с заданной структурой, которая может быть заполнена позже. Эти файлы будут добавлены в репозиторий, как только они будут созданы, и это будет раздражать, если вы начнете удалять или редактировать файлы .gitignore (и опасно, потому что, вероятно, вы даже не понимаете, что они не отслеживаются: git игнорирует их )
@Behnam: я возьму понижение, но мое исследование S.O. Мета не проявляет интереса к подробным ответам, поскольку они предоставляют достаточно деталей и ясности, чтобы быть полезными для каждого читателя (и каждого уровня навыков). Тем не менее, я очень открыт для любой критики, и спасибо, что публично объявили причину, я воспринимаю это очень позитивно.
Если вы измените свой ответ, чтобы заменить.gitkeep с любым другим именем файла без префикса git вы получите мое возражение, я думаю, что это лучший и наиболее информативный ответ. Причина: я думаю, что & quot; .git * & quot; должно быть зарезервировано для файлов, предписанных git, в то время как это просто заполнитель. Мое первое предположение, когда я увидел, что это, например, & quot; .gitkeep & quot; файл будет автоматически игнорироваться (это было бы неплохо), но это не так, верно?
Вы пропустили одну мысль - в чем причина хранения и пустой папки (например, / logs, / tmp, / uploads)? Да, его папка должна быть пустой. :) Так что если вы хотите оставить папку пустой, вы должны игнорировать файлы внутри нее.
3636

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

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

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

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

Изготовление@GreenAsJadeкомментарий постоянный:

I think it's worth noting that this solution does precisely what the question asked for, but is not perhaps what many people looking at this question will have been looking for. This solution guarantees that the directory remains empty. It says "I truly never want files checked in here". As opposed to "I don't have any files to check in here, yet, but I need the directory here, files may be coming later".

@pedromanoel Я пишу документацию, которую вы положили бы вREADME внутри.gitignore файл (как комментарии).
Технически это не пустой каталог ...
найдите 1 разницу: 1.) пустую папку, 2.) папку с файлом .gitignore. ;-)
Я думаю, что решение README, предложенное @JohnMee, должно использоваться вместе с этим; файл .gitignore содержит объяснение того, что мы хотим не допускать в управлении версиями, в то время как файл README объясняет назначение каталога, которые являются очень важной частью информации.
К сожалению, это приводит к непустому каталогу, у него есть один скрытый файл.
19

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

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

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

Если вы просто делаетеecho bla > file ты не получишьfile: File exists так как> перезапишет файл, если он уже существует, или создаст новый, если он не существует.
@clacke Если кто-то решит использовать оболочку, отличную от всех остальных, он должен прямо указать это, если у него возникнут проблемы. В отличие от национальности, у каждого есть свой свободный выбор снарядов.
Две вещи: Вы могли бы просто "повторить" * * & GT; TMP / .gitignore & Quot; вместо прикосновения, и "git commit -m" не фиксирует изменения, сделанные после того, как вы добавили файлы в индекс.
@SeldomNeedy Возможно, они ищут помощи, потому что даже не знают, что используют другую оболочку, чем все остальные.
/bin/sh культурное предположение! * Если & quot; здесь & quot; являетсяcsh и переменнаяnoclobber установлен, вы действительно получитеfile: File exists, Если кто-то говорит: «Я получил это», не думайте, что он «идиот, а отвечайте». Нет, вы не ». *c2.com/cgi/wiki?AmericanCulturalAssumption
4

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

8

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

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

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

Он хочет сохранить пустой каталог, а не файл.
@Wallacoloo Относительно вопроса, который вы правы, тем не менее, этот файл полезен, я буду использовать его для каталога загрузки, подобного тому, где файлы должны быть защищены .htaccess. Вопреки объяснению римлян, файл .htaccess будет зафиксирован, поскольку он исключен правилом игнорирования. [старая ветка, я знаю]
И я упомянул, что он также сохранит .htaccess. Пример: если в программном обеспечении есть каталог для лог-файлов (например, oxishop), который не должен быть доступен через Интернет, в каталоге есть .htaccess. Если вы поместите вышеупомянутый .gitignore в папку, .htaccess не будет завершен, и папка будет доступна через Интернет.
Если у вас есть файл .htaccess, который находится под контролем версий, то у вас уже есть каталог, содержащий его, под управлением версиями. Таким образом, проблема уже решена - файл .gitignore становится неактуальным.
14

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

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

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

12

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

Где-то где-то я читал напыщенную речь.

я нашелRe: Пустые каталоги .., но, возможно, есть еще один.

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

Я знаю, что вы опубликовали это как пример неверного аргумента, но я ценю ссылку, потому что это на самом деле аргументированный аргумент против отслеживания каталогов. ;-)
Патрик, он также использует слово «идиотский» там. Я подозреваю, что его формулировка адресована людям, находящимся здесь в этой теме, и поэтому я предполагаю, что он не будет реализовывать что-то «идиотское» в Git сам.
Этот ответ кажется противоречивым, поскольку в следующем посте в ссылочной теме Линус Торвальд говорит, что он ожидает, что им потребуется добавить отслеживание каталогов:markmail.org/message/libip4vpvvxhyqbl , На самом деле он говорит, что он "приветствовал бы патчи, которые [добавляют поддержку для отслеживания пустых каталогов]"
7

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

Я не вижу, как это может быть пустой тратой времени. Когда ваш TEMPLATEPATH явно динамический, вы не можете использовать решение .gitkeep. И даже с нединамической структурой папок вы должны добавить еще кое-что вместо удаления очень хорошего решения проверки каталогов, например проверьте разрешения и выполните chmod файлы. Добавление способа пометки каталогов внутри глобального .gitignore было бы для меня идеальным решением. Что-то вроде #keep / path / to / dir
Просто так, что мы все на одной странице, я больше этим не занимаюсь. Это пустая трата времени..gitkeep конвенция - намного лучшая практика.
30

Рубин на рельсах способ создания папки журнала:

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

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

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

echo log/dev.log >> .gitignore

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

Какое это имеет отношение к Ruby on Rails?
7

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

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.

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

fatal: Not a valid object name b64338b90b4209263b50244d18278c0999867193

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

Это на самом деле работает, но я думаю, что смущает IntelliJ ...: |
fatal хак.
27

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

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

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

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

Для просмотра каждого пустого каталога используйте следующую команду:

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

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

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

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

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

Чтобы вывести список всех файлов README после того, как они уже созданы:

find -name README.emptydir
5

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

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

Затем вы можете зафиксировать описательные файлы README.md (или пустые файлы, это не имеет значения), если вы можете назначить их уникальным образом, как с помощью*.md в этом случае) в каждом каталоге, чтобы убедиться, что все каталоги остаются частью репозитория, но файлы (с расширениями) игнорируются. ОГРАНИЧЕНИЕ:.в именах каталогов нельзя!

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

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

enter image description here

1017

Вы не можете ". УвидетьGit FAQ.

Currently the design of the git index (staging area) only permits files to be listed, and nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.

Directories are added automatically when adding files inside them. That is, directories never have to be added to the repository, and are not tracked on their own.

You can say "git add <dir>" and it will add files in there.

If you really need a directory to exist in checkouts you should create a file in it. .gitignore works well for this purpose; you can leave it empty, or fill in the names of files you expect to show up in the directory.

Я видел много репозиториев, в которых используется пустой файл.gitkeep для этого.
Хорошо, если кто-то хочет переместить файлы в новый каталог, он не может сделать это черезgit mv как мерзавец будет жаловаться, что новый каталог не находится под контролем версий
Вы можете прочитать & quot;it's impossible, you can't, etc.& Quot; по всему интернету на этот частый вопрос..gitignore Трюк является частым ответом и удовлетворяет многие потребности. тем не мениеit IS possible чтобы сделать git отслеживатьtruly empty каталог,see my answer
Хотя чем больше я об этом думаю, тем больше это похоже на «SHA-хэш пустой строки», если он существует, на самом делеwould быть четко определенным идентификатором для пустого дерева, если только невозможно определить, является ли этот объект деревом или большим двоичным объектом.
Ниже ответ НАМНОГО лучше. Тот факт, что git низкоуровневого программного обеспечения не позволяет, для меня не так важно, как на самом деле использовать Git, когда мне нужен пустой каталог. Добавление 2 строки .gitignore кажется приемлемым для меня.
285
touch .keep

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

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

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

Было предложеноgit clean -nd | sed s/'^Would remove '// | xargs -I{} touch "{}.keep" будет делать это во всех неотслеживаемых пустых каталогах.
Вопрос и основная общая проблема заключается в добавлении пустого каталога. Если позже у него есть резидентный файл, очевидно, удалите.keep файл или просто игнорировать его. Если вместо этого файлы в каталоге должны быть проигнорированы, то это совсем другой вопрос.
Не нравится это решение, трудно догадаться, что делает этот файл. Кроме того, если вы генерируете файлы в своей среде разработки (например, журналы или изображения и т. Д.), Это не удерживает эти файлы от создания версий и их запуска в производство, что нехорошо.
Это хорошо для начальной пустой директории, но что, если она начнет заполняться файлами? Тогда Git заметит их и потребует их как неотслеживаемые файлы. Выбранный ответ здесь работает гораздо более элегантно, позволяя хранить каталог, но затем безопасно игнорировать его содержимое.
Windows не любит файлы без имен, и для этого требуется специальная магия (так называемое терминальное приложение, похожее на bash или аналогичное).
3

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

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

Формат, как уже упоминалось, это:

*
!.gitignore

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

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

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

#!/bin/bash

dir=''

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

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

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

$ ignore_dir ./some/directory

Другой вариант (в ответ на комментарий @GreenAsJade), если вы хотите отслеживать пустую папку, котораяMAY содержать отслеживаемые файлы в будущем, но пока пустыми, вы можете опустить* от.gitignore файл и проверитьthat в. По сути, все, что файл говорит "не игнорироватьme& quot ;, но в остальном каталог пуст и отслеживается.

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

!.gitignore

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

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

391

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

Согласен. Пустые папки раздражают и должны быть объяснены во всех должным образом обработанных репозиториях любого вида.
+1, Хорошее предложение, пустой каталог не имеет никакого смысла, если он не будет использоваться в будущем. Поэтому создайте файл README внутри него и напишите, для чего этот каталог, и какие файлы будут помещены туда в будущем. Это решает обе проблемы.
@Jez: я не согласен. Дело в том, что git предназначен для контроля (и индексации) исходного кода. Важно, что идентификатор коммита - это хэш содержимого. То есть оно должно иметь содержание. Вы не нуждаетесь в README вevery часть дерева, только листовые узлы. Если у вас есть места, в которые вы намереваетесь поместить код, но не код, и вы даже не потратите время, чтобы повторить «место для моделей» & GT; & GT; README, тогда у вас есть идея, а не коммит. Гит не интересен. Говоря "Я хочу, чтобы у запущенного приложения были пустые каталоги XYZ" этоruntime проблема, а не проблема источника. Обращайтесь с вашим установщиком.
@ jbo5112 Да, специальный код & quot; Вы ссылаетесь на «Установщик» Я упомянул. Ваша установка веб-приложения уже должна обрабатывать создание базы данных, локальную конфигурацию, вытягивание зависимостей или 100 других операций, но пара пустых каталогов выходит за рамки этого? Попробуйте gradle, passenger, chef, примитивный Makefile и т. Д. Нет никакой разницы в безопасности между созданием каталогов и другой (потенциально гораздо более сложной / опасной) работой по установке приложения. И если у вас действительно нет deps, config, DB и т. Д., И нет установщика, тогда просто используйте README. Ни один случай не требует от вас обоих.
@ilius Ерунда. Структура каталогов, содержащих пустые каталоги, может быть весьма желательной во многих ситуациях (например, приложение MVC, где вы хотите каталог моделей, но пока не удосужились создать какие-либо модели, или каталог общих представлений, в который вы планируете добавить общие представления, позже ). Более того, помещать README в каждый из них является излишним, поскольку очевидно, для чего они предназначены, и легко забыть поместить README в каждый из них. И вы должны помнить, чтобы удалить README, когда вы добавите к ним некоторые другие файлы. По сути, git должен разрешать пустые каталоги.
20

Может быть, добавление пустой директории кажетсяpath of least resistance потому что у вас есть сценарии, которые ожидают, что этот каталог существует (возможно, потому что он является целью для сгенерированных двоичных файлов). Другой подход будетmodify your scripts to create the directory as needed.

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

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

ln -sf .generated/bin bin
git add bin

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

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

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

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

.generated
Примечание. Символическая ссылка, которую я предложил, является "неработающей". в чистой кассе, потому что.generated Каталог изначально не существует. Он больше не будет сломан, как только вы сделаете свою сборку.
Я согласен, что в некоторых случаях это очень хорошая идея, но в других (например, при распространении проекта, в котором у вас есть пустой скелет с папками, такими как модели / и представления /), вы бы хотели, чтобы пользователь имел эти каталоги под рукой, а не чем читать вручную документы, и можно ожидать, что после клонирования репозитория они запустят какой-то инсталляционный скрипт. Я думаю, что этот ответ в сочетании с ответом README @ john-mee должен охватывать большинство, если не все случаи.
4

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

Я оспариваю это мнение.Structure доволен, и все, что выname вносит свой вклад в содержание.
Пустой файл не является ни исходным кодом, ни содержимым. Это просто имя. Тем не менее, Git с радостью отследит пустые файлы. Я не думаю, что это было намеренное дизайнерское решение заставить Git отказаться от отслеживания пустых каталогов. Я думаю, что отслеживание пустых каталогов - это функция, которой просто не требуется 99% времени, поэтому они не удосужились выполнить дополнительную работу, необходимую для правильной работы. Git может сделать это, если кто-то сильно хочет эту функцию для ее реализации. Я сомневаюсь, что сопровождающие Git были бы против такого исправления, если бы оно было сделано правильно.
Не совсем согласен. Я могу найти различные причины, почему я хочу отслеживать пустую папку. Например, я разрабатываю очень легкий PHP MVC-фреймворк для своих проектов. У меня есть определенные папки для размещения моделей, видов и т. Д. Когда я создаю новый сайт на основе моей платформы, эти папки пусты, так как по умолчанию моделей или видов нет, но мне нужна папка для существования, иначе мой фреймворк выиграл и снова не работает!
@TobyAllen вот обновленныйFAQ link Верхний ответ также является тем, что рекомендуется в FAQ с более точными инструкциями.
Это отсутствующая особенность (и низкий приоритет), а не преднамеренное ограничение. Из Git FAQ: В настоящее время дизайн индекса Git (промежуточная область) разрешает только перечисление файлов, иnobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.
7

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

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

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

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

121

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

find . -type d -empty -exec touch {}/.gitignore \;
Более простой вариант для большинства ситуацийfind * -type d -empty -exec touch {}/.gitignore \;
Вы можете игнорировать каталог .git:find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \;
Кто-нибудь знает способ сделать это в Windows из командной строки? Я видел некоторые решения здесь, в Ruby и Python, но мне нравится простое решение, если им можно управлять.
Поскольку OS X создает файл .DS_Store почти в каждой директории, это не работает там. Единственный (ОПАСНЫЙ!) Обходной путь, который я нашел, - сначала удалить все файлы .DS_Store с помощьюfind . -name .DS_Store -exec rm {} \; и затем используйте предпочтительный вариант из этого ответа. Обязательно выполняйте это только в правильной папке!
2

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

В прошлом я помещал файл .gitignore в корень моего репозитория, а затем исключал папку, например:

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

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

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

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

*
!.gitignore

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

2

Вы можете сохранить этот код как 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
10

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

25

WARNING: This tweak is not truly working as it turns out. Приносим извинения за неудобства.

Original post below:

Я нашел решение, играя с внутренностями Git!

Suppose you are in your repository.

Create your empty directory:

$ mkdir path/to/empty-folder

Add it to the index using a plumbing command and the empty tree SHA-1:

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

Type the command and then enter the second line. Press Enter and then Ctrl + D to terminate your input. Note: the format is mode [SPACE] type [SPACE] SHA-1hash [TAB] path (the tab is important, the answer formatting does not preserve it).

That's it! Your empty folder is in your index. All you have to do is commit.

Это решение короткое и, видимо, работает нормально (see the EDIT!), но это не так легко запомнить ...

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

EDIT:

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

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

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

Для любопытных, он работает на интерфейсе GitHub:github.com/cirosantilli/test-empty-subdir , но когда вы клонируете его, он не проверяется.
После помещения пустой папки в индекс и фиксации, можно лиgit svn dcommit это с желаемым результатом?
@PyRulez хорошо, в мире программного обеспечения нет ничего невозможного. : D Собственно, я последовал за ответом.
@ CiroSantilli & # x516D; & # x56DB; & # x4E8B; & # x4EF6; & # x6CD5; & # x8F6E; & # x529F; & # x5305; & # x5353; & # x8F69; Я получил этот тип пустого каталогаgithub.com/abhisekp/empty-dir
Маловероятно, что этот твик будет работать с любым другим инструментом. Как указано в предупреждении и редактировании, я не рекомендую использовать его, если только в весьма ограниченном случае.
59

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

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

Конечно, этот дополнительный ответ действительно указывает на факт.
Извините, я не прочитал последний абзац, и хотя я прочитал первый абзац, я не уверен, почему я повторил эту информацию.
Это именно то, что я сказал. Оба параграфа рассмотрены во фрагменте часто задаваемых вопросов, которые я разместил.
Я думаю, что это неинтересно и полезно знать - это можно исправить, просто не ожидайте этого в ближайшее время, когда в большинстве случаев есть такой простой обходной путь.
Я попал сюда, рассматривая случай, когда сборка не работает, если каталог не существует, и по умолчанию он пуст, но он не должен быть пустым. Создание .gitignore делает правильные вещи.
8

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

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

Я вставил это в Rakefile для быстрого доступа.

Я бы предпочел использоватьfind . -type d -empty -print0 | xargs --null bash -c 'for a; do { echo "*"; echo "!.gitignore"; } >>"$a/.gitignore"; done' --
10

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

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

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

Edit for a better solution

Итак, так как большинство наших разработчиков ужеМуравей сначала я подумал о том, чтобы собрать файл сборки Ant, чтобы выполнить это независимо от платформы. Это еще можно найтиВот

HoweverПозже я подумал, что было бы лучше превратить это в небольшую служебную команду, поэтому я воссоздал ее с помощью Python и опубликовал в PyPIВот, Вы можете установить его, просто запустив:

pip3 install gitkeep2

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

$ gitkeep --help
Usage: gitkeep [OPTIONS] PATH

  Add a .gitkeep file to a directory in order to push them into a Git repo
  even if they're empty.

  Read more about why this is necessary at: https://git.wiki.kernel.org/inde
  x.php/Git_FAQ#Can_I_add_empty_directories.3F

Options:
  -r, --recursive     Add or remove the .gitkeep files recursively for all
                      sub-directories in the specified path.
  -l, --let-go        Remove the .gitkeep files from the specified path.
  -e, --empty         Create empty .gitkeep files. This will ignore any
                      message provided
  -m, --message TEXT  A message to be included in the .gitkeep file, ideally
                      used to explain why it's important to push the specified
                      directory to source control even if it's empty.
  -v, --verbose       Print out everything.
  --help              Show this message and exit.

Я надеюсь, что вы найдете это полезным.

Похожие вопросы