#git
Вопрос:
У меня есть следующая настройка:
mkdir /base; cd /base git init a touch a/file.txt git init b cd b git config core.worktree=/base git add ../a/file.txt
У меня есть /base
папка, которая содержит два репозитория ( a
и b
). Репо a
содержит только файл (даже не зафиксированный). Репо b
устанавливает рабочее дерево в /base
(где находятся оба репо). Когда я пытаюсь добавить file.txt
из репо a
, это не сработало (оно просто не поставлено).
Когда я удаляю .git
папку a
, я могу добавить файл.
rm -rf ../a/.git git add -vvv ../a/file.txt
Я не совсем понимаю, почему это так. Может быть, git запрещает добавлять файл, потому что он думает, что это подмодуль? Я пытался предотвратить это с помощью некоторых настроек подмодуля, но безрезультатно.
git config submodule.ignore all git config submodule.active false
Как я могу обмануть git, чтобы принудительно добавить файл? ( -f
предназначен только для игнорируемых файлов и -v
не дает никакой информации).
ИЗМЕНИТЬ: Я справился с этим, временно переименовав .git
папку со следующим сценарием:
# Check if there is a .git folder. If so, we need to temporary # rename it, so we can track the file/folder. GIT_DIR= TRAVERSAL_PATH="$RESOURCE_TO_TRACK" while [[ "$TRAVERSAL_PATH" != "/" ]]; do if [[ -d "$TRAVERSAL_PATH/.git" ]]; then GIT_DIR="$TRAVERSAL_PATH/.git" break fi TRAVERSAL_PATH="$(dirname $TRAVERSAL_PATH)" done [[ "$GIT_DIR" != "" ]] amp;amp; mv "$GIT_DIR" "$GIT_DIR.keep" git add -v -f "$RESOURCE_TO_TRACK" [[ "$GIT_DIR" != "" ]] amp;amp; mv "$GIT_DIR.keep" "$GIT_DIR"
$RESOURCE_TO_TRACK
это файл папки, которую я хочу добавить в репозиторий. После первоначального добавления мое репо отслеживает изменения и дальнейшую работу по добавлению/фиксации, как и ожидалось.
Ответ №1:
Ты не можешь.
Точнее, путь к файлу в каком-либо коммите должен состоять только из «нисходящих» компонентов, все из которых находятся в этом репозитории, а не в каком-либо другом репозитории файловой системы. Поэтому , если путь к файлу ../dir/file
указан, вы не можете его добавить , а если имя файла dir/sub/file
dir/sub
содержит a .git
, вы не можете его добавить.
Это последнее ограничение является ограничением подмодуля:
Может быть, git запрещает добавлять файл, потому что он думает, что это подмодуль?
Это подмодуль, если он находится в другом каталоге с a .git
в нем.
Вы можете обойти ограничение на подмодуль , используя git update-index
, но если вы это сделаете, вы забредете на опасную территорию:
$ git hash-object -w dir/sub/foo e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 $ git update-index --add --cacheinfo 100644,e69de29bb2d1d6434b8b29ae775ad8c2e48c5391,dir/sub/foo
То, что происходит в этот момент, не очень четко определено dir/sub
, действительно ли это репозиторий Git. (Я создал временную пару репозиториев для выполнения этих команд и больше здесь ничего не проверял.) Обратите внимание, что ../
это недопустимо в качестве компонента пути:
$ git update-index --add --cacheinfo 100644,e69de29bb2d1d6434b8b29ae775ad8c2e48c5391,../sub/foo error: Invalid path '../sub/foo' fatal: git update-index: --cacheinfo cannot add ../sub/foo
Комментарии:
1. Я /могу/, как упоминалось в моем вопросе (переименовать/удалить папку .git). Я обновил свой вопрос и добавил ответ на свою проблему.
2. Ваш метод, вероятно, будет работать нормально, просто имейте в виду, что субрепо будет думать, что это неотслеживаемый файл, если/пока вы не добавите его туда, после чего два мерзавца будут сражаться друг с другом из-за файла. (Вот что я имею в виду под «не очень четко определена»: это также не поддерживаемая конфигурация, поэтому, если что-то пойдет не так, вы будете предоставлены сами себе.) Обратите внимание, что вложенные вложенные репозитории вызовут проблему для вашего скрипта, который выполняет поиск вверх только один раз, а не до текущего каталога.
Ответ №2:
Пожалуйста, прочтите важное примечание внизу для лучшего альтернативного решения!
Буквальный ответ на заданный вопрос
Хотя вы не можете, как очень хорошо объяснил торек, есть обходной путь.
Вы можете отредактировать свой файл b
и скопировать его a
с помощью скрипта. Вот ваша настройка:
/base |- a | |- .gitignore |- b |- copy-file |- resources |- file.txt
/base/b/resources/file.txt
это ваш файл, который должен принадлежать/base/a
, но версия в/base/b
нем ./base/b/copy-file
это скрипт, который копирует файл в нужное место, не забудьте сделать его исполняемым./base/a/.gitignore
игнорируетfile.txt
, чтобы скопированный файл не был версионным/base/a
.
Ваш рабочий процесс состоит в следующем:
- Обновите все свои филиалы.
- Запустите
/base/b/copy-file
(возможно, с помощью крючков git), которые разместят неверсированную копию вашегоfile.txt
in/base/a
. - Начинай работать.
Важное примечание
Я знаю, что кажется заманчивым сделать это таким образом из-за причин, которые подтолкнули вас к вашему текущему рабочему процессу, но даже если бы я ответил на ваш вопрос как есть, я также предлагаю вам рассмотреть различные подходы. Например:
- Держите
copy-file
сценарий при/base
себе . Вероятно, есть причина, по которой вы не выполнили ни одного проекта с обеими этими подпапками. Этой причиной должна быть возможность повторного использования. Если вы определяете относительный путь к своемуa
подкаталогу в своемb
репозитории, это означает, что они каким-то образом связаны и взаимозависимы. Что подводит меня к следующему и лучшему решению: - Используйте менеджер пакетов! Я уверен, что в вашем языке есть один из тех модных менеджеров пакетов, они повсюду! Поэтому используйте
npm
,pip
,composer
или любой другой, с которым работает ваш язык, сделайте так, чтобы вашb
подпроект требовал вашегоa
подпроекта (или наоборот, не совсем понятно, что требуется в вашем вопросе) и используйте пространства имен для ссылки на удаленный файл, когда он вам нужен в другом подпроекте. Обычно вам не нужно публиковать один из ваших подпроектов, чтобы использовать официальный веб-сайт менеджера пакетов, у вас должен быть способ включить репозиторий Git.