После получения более полного объяснения того, что происходит, я думаю, что понимаю это, и в любом случае внизу у меня есть обходной путь. В частности, я считаю, что обнаружение переименования обманывается слиянием поддерева с --prefix. Вот мой тестовый пример:
mkdir -p z/a z/b
cd z/a
git init
echo A>A
git add A
git commit -m A
echo AA>>A
git commit -a -m AA
cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB
cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
git read-tree --prefix=bdir -u B/master
git commit -m "subtree merge B into bdir"
cd bdir
echo BBB>>B
git commit -a -m BBB
Мы создаем каталоги git a и b с несколькими коммитами каждый. Мы делаем слияние поддерево, а затем мы делаем
окончательный коммит в новом поддереве.
Запуск gitk
(в z / a) показывает, что история действительно появляется, мы можем ее видеть. Запуск git log
показывает, что история действительно появляется. Однако при просмотре определенного файла возникает проблема: git log bdir/B
Ну, есть трюк, который мы можем сыграть. Мы можем посмотреть историю переименования конкретного файла, используя --follow. git log --follow -- B
. Это хорошо, но не очень, поскольку не удается связать историю предварительного слияния с последующим слиянием.
Я попытался поиграть с -M и -C, но не смог заставить его следовать одному конкретному файлу.
Итак, я считаю, что решение состоит в том, чтобы сообщить git о переименовании, которое будет происходить как часть слияния поддерева. К сожалению, git-read-tree довольно суетлив относительно слияний поддеревьев, поэтому нам нужно работать через временный каталог, но это может уйти, прежде чем мы сделаем коммит. После этого мы можем увидеть полную историю.
Сначала создайте репозиторий «А» и сделайте несколько коммитов:
mkdir -p z/a z/b
cd z/a
git init
echo A>A
git add A
git commit -m A
echo AA>>A
git commit -a -m AA
Во-вторых, создайте репозиторий "B" и сделайте несколько коммитов:
cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB
И хитрость в том, чтобы заставить эту работу : заставить Git распознать переименование, создав подкаталог и переместив в него содержимое.
mkdir bdir
git mv B bdir
git commit -a -m bdir-rename
Вернитесь в хранилище "A", получите и объедините содержимое "B":
cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
# According to Alex Brown and pjvandehaar, newer versions of git need --allow-unrelated-histories
# git merge -s ours --allow-unrelated-histories --no-commit B/master
git read-tree --prefix= -u B/master
git commit -m "subtree merge B into bdir"
Чтобы показать, что они теперь объединены:
cd bdir
echo BBB>>B
git commit -a -m BBB
Чтобы доказать, что вся история сохраняется в связанной цепочке:
git log --follow B
После этого мы получаем историю, но проблема в том, что если вы на самом деле держите старое репо «б» и время от времени сливаетесь с ним (скажем, на самом деле это репо, поддерживаемый отдельно третьей стороной), то у вас проблемы эта третья сторона не сделала переименование. Вы должны попытаться объединить новые изменения в вашей версии b с переименованием, и я боюсь, что это не пройдет гладко. Но если б уходит, вы выиграете.