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

#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 .

Ваш рабочий процесс состоит в следующем:

  1. Обновите все свои филиалы.
  2. Запустите /base/b/copy-file (возможно, с помощью крючков git), которые разместят неверсированную копию вашего file.txt in /base/a .
  3. Начинай работать.

Важное примечание

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

  • Держите copy-file сценарий при /base себе . Вероятно, есть причина, по которой вы не выполнили ни одного проекта с обеими этими подпапками. Этой причиной должна быть возможность повторного использования. Если вы определяете относительный путь к своему a подкаталогу в своем b репозитории, это означает, что они каким-то образом связаны и взаимозависимы. Что подводит меня к следующему и лучшему решению:
  • Используйте менеджер пакетов! Я уверен, что в вашем языке есть один из тех модных менеджеров пакетов, они повсюду! Поэтому используйте npm , pip , composer или любой другой, с которым работает ваш язык, сделайте так, чтобы ваш b подпроект требовал вашего a подпроекта (или наоборот, не совсем понятно, что требуется в вашем вопросе) и используйте пространства имен для ссылки на удаленный файл, когда он вам нужен в другом подпроекте. Обычно вам не нужно публиковать один из ваших подпроектов, чтобы использовать официальный веб-сайт менеджера пакетов, у вас должен быть способ включить репозиторий Git.