Поддерево Git делится поддеревьями с участниками

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

Вот сценарий:

  1. Я владею основным репозиторием X и отправляю его в источник.
  2. Мой коллега извлекает репозиторий X из источника, добавляет поддерево, указывающее на другой репозиторий Y, делает коммит и отправляет X обратно в источник.
  3. Я нажимаю X и вижу изменения, внесенные моим коллегой. Однако в моем локальном репозитории папка, содержащая поддерево Y, — это просто еще один файл. Я не могу извлечь изменения из репо Y даже после добавления репо Y в качестве удаленного. Поддерево Git всегда говорит, что папка уже существует, когда я делаю git subtree add, и говорит, что не может найти фиксацию, когда я делаю git subtree merge.

Кто-нибудь знает лучший способ справиться с этой ситуацией? В идеале я хотел бы также иметь возможность извлекать изменения из репо Y, хотя я не являюсь пользователем, добавляющим репо Y в качестве поддерева репо X. Возможно ли это? Если нет, то как лучше всего поделиться репозиториями с поддеревьями?


person bow    schedule 11.03.2014    source источник
comment
обычно, когда ваш коллега добавляет репозиторий Y в качестве поддерева, все файлы и папки должны присутствовать внутри папки, содержащей поддерево Y   -  person Chris Maes    schedule 11.03.2014
comment
руководство по использованию git-subtree можно найти на этой странице: psionides.eu/2010/02/04/   -  person Chris Maes    schedule 11.03.2014
comment
Да, файлы есть. Проблема в том, что когда я хочу синхронизировать изменения из репозитория Y себя, я не могу этого сделать. Я добавил репозиторий Y в качестве удаленного в моем локальном репозитории X, но он не работает. Добавление поддерева говорит, что это невозможно, так как файлы действительно уже есть. Слияние поддеревьев говорит об отсутствующей фиксации.   -  person bow    schedule 11.03.2014
comment
обычно, когда вы делаете клон git из удаленного репозитория X, вам не нужно ничего менять; просто добавьте пульт... если вы говорите, что хотите синхронизировать, вы имеете в виду потянуть и объединить?   -  person Chris Maes    schedule 11.03.2014
comment
да. Я также хочу получить и объединить из репозитория Y в репо X, сохраняя репо Y как поддерево X. Я знаю удаленный URL-адрес, я знаю, что это поддерево репо X, но я не знаю, как также извлекать и объединять изменения из репозитория Y.   -  person bow    schedule 11.03.2014
comment
обычно эти команды должны делать свое дело: git fetch sub (или git fetch --all) git subtree merge -P subdir -m объединил изменения подчиненного подчиненного/мастера. Если не; пожалуйста, опубликуйте точное сообщение об ошибке.   -  person Chris Maes    schedule 11.03.2014
comment
о, и кстати; ваш коллега импортировал поддерево с командой squash или без нее? Вам нужно сделать то же самое: см. примечания в ссылке, которую я предоставил.   -  person Chris Maes    schedule 11.03.2014
comment
также: проверьте свою историю git; вы должны увидеть коммиты как из репозитория X, так и из Y. Если ваш коллега использовал сквош, вы должны увидеть по крайней мере один сжатый коммит из репо Y.   -  person Chris Maes    schedule 11.03.2014
comment
@bow Может быть полезно, если вы опубликуете точные команды, с которыми вы пытаетесь использовать git subtree merge.   -  person Maic López Sáenz    schedule 13.03.2014


Ответы (2)


Используйте 1_.

git subtree add добавляет историю другого репозитория в качестве нового поддерева — в вашем случае это сделал ваш коллега, так что это не сработает

git subtree merge объединяет изменения до заданной локальной фиксации в поддерево — поскольку вы еще не получили эти изменения, это также не сработает

git subtree pull извлекает изменения из другого репо, а затем объединяет их в поддерево. Протестировано со следующей последовательностью команд (используется ветвь «master» репозитория поддерева, при необходимости настройте).

~ $ mkdir subrepo
~ $ cd subrepo
~/subrepo $ git init
Initialized empty Git repository in ~/subrepo/.git/
~/subrepo $ touch file
~/subrepo $ git add file
[master (root-commit) 03a9f75] file added
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file
~/subrepo $ cd ..
~ $ mkdir repo1
~ $ cd repo1
~/repo1 $ git init
Initialized empty Git repository in ~/repo1/.git/
~/repo1 $ git commit --allow-empty -m "initial commit"
[master (root-commit) ec7e1c5] initial commit
~/repo1 $ git subtree add --prefix=sub ../subrepo master
git fetch ../subrepo master
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../subrepo
 * branch            master     -> FETCH_HEAD
Added dir 'sub'
~/repo1 $ cd ..
~ $ git clone repo1 repo2
~ $ cd subrepo
~/subrepo $ echo 'new version' > file
~/subrepo $ git add file
~/subrepo $ git commit -m "file changed"
[master c72ac6e] file changed
 1 file changed, 1 insertion(+)
~/subrepo $ cd ../repo2
~/repo2 $ git subtree pull --prefix=sub ../subrepo master
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../subrepo
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 sub/file | 1 +
 1 file changed, 1 insertion(+)
~/repo2 $ cat sub/file
new version
person Grzegorz Herman    schedule 19.03.2014
comment
Хм.. странно :/. В проблемном репозитории, над которым я работаю, у меня есть ошибка fatal: entry not found in tree {commit_hash}. Затем я сделал git show {commit_hash} и увидел фиксацию (это фиксация субрепозитория). - person bow; 20.03.2014
comment
Подожди, я понял, что не так. pull действительно наконец работает, и проблема заключается в дополнительной косой черте / в аргументе префикса, который я использую. Я не ожидал, что --prefix будет чувствителен к этому, но, видимо, так оно и есть. В любом случае, спасибо, что указали мне правильное направление :). - person bow; 20.03.2014

Обычно эти команды должны удовлетворять все ваши потребности; если вы не испортили вещи в процессе. Обратите внимание на проблемы со Squash на этом сайте

добавить репозиторий как поддерево в другом

cd super
git remote add sub git@gitlab:chris.maes/sub.git
git fetch sub #or use: git fetch --all
git subtree add -P subdir -m "add sub as subtree in subdir" sub/master

объединить изменения в подпроекте в суперпроект

git fetch sub (or git fetch --all)
git subtree merge -P subdir -m "merged changes of sub" sub/master

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

git subtree split -P subdir -b backport
git push sub backport:master
person Chris Maes    schedule 11.03.2014
comment
Это работает для отправки изменений из репозитория X в удаленный репо Y (что достаточно хорошо задокументировано). Моя проблема заключается в том, что я не могу перенести изменения из репозитория Y в локальный репозиторий X, потому что это мой коллега добавил репозиторий Y в качестве поддерева X вместо меня. Когда я делаю subtree add, git subtree отказывается делать это, говоря, что каталог для Y уже существует (потому что мой коллега уже добавил его). - person bow; 11.03.2014
comment
это потому, что вам больше не нужно добавлять поддерево git, просто слияние поддерева git... - person Chris Maes; 12.03.2014