Git: поддерево слиться в глубоко вложенный подкаталог? - PullRequest
19 голосов
/ 06 мая 2011

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

Я следовал указаниям здесь , чтобы добавить репозиторий модулей в качестве удаленного, запустив git read-tree, чтобы получить удаленный код в подкаталог в моем локальном репо и зафиксировать эти изменения.

Моя проблема возникает, когда я пытаюсь вытянуть и объединить изменения с пульта в главную ветвь моего основного проекта. Шаг 5 на странице выше предлагает git pull с переключателем поддерева -s. Это правильно работает для меня, когда мой подкаталог имеет глубину один, два или три уровня, но не четыре.

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

$ git pull -s subtree REMOTE_REPO master
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /path/to/my/REMOTE_REPO
 * branch            master     -> FETCH_HEAD
Merge made by subtree.
 sites/all/README |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

Здесь подкаталог имеет 3 уровня глубины: sites / all / modules /. Это тоже отлично работает, вытягивая изменения и обновляя файлы.

$ git pull -s subtree REMOTE_REPO master
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /path/to/my/REMOTE_REPO
 * branch            master     -> FETCH_HEAD
Merge made by subtree.
 sites/all/modules/README |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

Но теперь мой код находится в подкаталоге глубиной 4 уровня: sites / all / modules / my_module /. Git, похоже, извлекает изменения из REMOTE_REPO, но не обновляет файлы, а вместо этого говорит мне, что он уже обновлен.

$ git pull -s subtree REMOTE_REPO master
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /path/to/my/REMOTE_REPO
 * branch            master     -> FETCH_HEAD
Already up-to-date!
Merge made by subtree.

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

$ git pull -s subtree REMOTE_REPO master
From /path/to/my/REMOTE_REPO
 * branch            master     -> FETCH_HEAD
Already up-to-date.

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

Это ошибка, или я что-то не так делаю?

Обновление: Крис Джонсен предложил следующую опцию, которая выдает ошибку:

$ git pull -X subtree=sites/all/modules/my_module/ REMOTE_REPO master
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /Users/jeff/work/checkouts/compass_suite
 * branch            master     -> FETCH_HEAD
fatal: entry  not found in tree 173d4f16af4d2d61ae5c4b3446c392e8b49cc57d

Ответы [ 2 ]

54 голосов
/ 07 ноября 2012

Разъяснение для будущих читателей, решение в комментариях Криса Джонсена.Если вы видите ошибку «fatal: entry not found in tree», уберите косую черту в конце префикса вашего поддерева.

Например, если вы пытаетесь получить поддерево GitHub Pages.с такой командой, как

git subtree --prefix gh-pages/ pull origin gh-pages

, и возникают конфликты, вы получите сообщение об ошибке, например

 * branch            gh-pages   -> FETCH_HEAD
fatal: entry  not found in tree 6e69aa201cad3e5888f1d12af0d910f8a10a8ec3

Просто удалите косую черту из каталога gh-pages

git subtree --prefix gh-pages pull origin gh-pages

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

Automatic merge failed; fix conflicts and then commit the result.

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

10 голосов
/ 06 мая 2011

Стратегия слияния subtree искусственно ограничивает глубину поиска того, где поддерево «вписывается» в общее дерево. К сожалению, этот предел жестко закодирован (см. match-trees.c:267).

К счастью, Git 1.7.0 добавил опцию subtree=… в стратегию слияния (по умолчанию) recursive. Эта опция позволяет вам точно указать префикс, так что Git не нужно угадывать (столько).

С Git 1.7.0 или новее попробуйте это:

git pull -X subtree=sites/all/modules/my_module REMOTE_REPO master
...