Я хотел бы объединить удаленный репозиторий git в моем рабочем репозитории git в качестве его подкаталога. Я бы хотел, чтобы полученный репозиторий содержал объединенную историю двух репозиториев, а также чтобы каждый файл объединенного репозитория сохранял свою историю, как это было в удаленном репозитории. Я попытался использовать стратегию поддерева, как упоминалось в разделе Как использовать стратегию слияния поддерева , но после выполнения этой процедуры, хотя полученный репозиторий действительно содержит объединенную историю двух репозиториев, отдельные файлы, поступающие с удаленного, не сохранили свою историю (`git log 'на любом из них просто показывает сообщение« Объединенная ветка ... »).
Также я не хочу использовать подмодули, потому что я не хочу, чтобы два объединенных репозитория git больше были отдельными.
Можно ли объединить удаленный репозиторий git в другой как подкаталог с отдельными файлами, поступающими из удаленного репозитория, с сохранением их истории?
Большое спасибо за любую помощь.
EDIT: в настоящее время я пробую решение, которое использует git filter-branch для перезаписи истории объединенного репозитория. Кажется, это работает, но мне нужно еще немного протестировать. Я вернусь к отчету о своих выводах.
РЕДАКТИРОВАТЬ 2: В надежде, что я прояснюсь, я даю точные команды, которые я использовал со стратегией git subtree, что приводит к очевидной потере истории файлов удаленного репозитория. Пусть A будет репозиторием git, над которым я сейчас работаю, а B - репозиторием git, который я хотел бы включить в A в качестве его подкаталога. Он сделал следующее:
git remote add -f B <url-of-B>
git merge -s ours --no-commit B/master
git read-tree --prefix=subdir/Iwant/to/put/B/in/ -u B/master
git commit -m "Merge B as subdirectory in subdir/Iwant/to/put/B/in."
После этих команд и перехода в каталог subdir / Iwant / to / put / B / in, я вижу все файлы B, но git log
на любом из них отображается только сообщение фиксации «Merge B as subdirectory in subdir / Iwant / to / put / Б / дюйм " Их файловая история, как в B, потеряна.
Что , кажется , на работу (так как я новичок на мерзавец я могу ошибаться) , заключается в следующем:
git remote add -f B <url-of-B>
git checkout -b B_branch B/master # make a local branch following B's master
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&subdir/Iwant/to/put/B/in/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
git checkout master
git merge B_branch
Приведенная выше команда для filter-branch взята из git help filter-branch
, в котором я только изменил путь к подкаталогу.
gitk
говорит об истории? Раньше я успешно использовал git subtree merge. Возможно, вы сможете раскрыть свои точные команды? Я не уверен, что git-filter-branch - правильный подход. Я мог бы порекомендовать попробовать git-fast-export и git-fast-import, чтобы синтезировать новую историю.gitk
показаны два репозитория, объединенных в их подсказках и не связанных в их начальных фиксациях. (Помогло бы я, если бы я разместил скриншоты просмотра истории gitk? Могу ли я?) К сожалению, отдельные файлы удаленного репозитория не сохранили свою историю, если я это сделаю в терминалеgit log <file-from-remote-repo>
. Я смотрюgit-fast-export
иgit-fast-import
; Я новичок в git. Я отредактирую свой вопрос, чтобы показать, какие именно команды я использовал с git subtree. Большое спасибо за ваш ответ.Ответы:
После получения более полного объяснения того, что происходит, я думаю, что понимаю это, и в любом случае у меня есть обходной путь. В частности, я считаю, что обнаружение переименования обманывается слиянием поддерева с --prefix. Вот мой тестовый пример:
Мы создаем каталоги git a и b с несколькими коммитами в каждом. Мы выполняем слияние поддеревьев, а затем совершаем финальную фиксацию в новом поддереве.
Запуск
gitk
(в з / а) показывает, что история действительно появляется, мы ее видим. Бегgit log
показывает, что история действительно появляется. Однако при просмотре конкретного файла возникает проблема:git log bdir/B
Что ж, есть трюк, в который мы можем сыграть. Мы можем посмотреть историю предварительного переименования конкретного файла, используя --follow.
git log --follow -- B
. Это хорошо, но не очень, поскольку не может связать историю предварительного слияния с историей после слияния.Я попытался поиграть с -M и -C, но мне не удалось заставить его следовать за одним конкретным файлом.
Итак, решение, как мне кажется, состоит в том, чтобы сообщить git о переименовании, которое будет происходить как часть слияния поддерева. К сожалению, git-read-tree довольно привередливо относится к слияниям поддеревьев, поэтому мы должны работать через временный каталог, но это может исчезнуть до того, как мы зафиксируем. После этого мы можем увидеть полную историю.
Сначала создайте репозиторий «А» и сделайте несколько коммитов:
Во-вторых, создайте репозиторий "B" и сделайте несколько коммитов:
И хитрость, чтобы заставить эту работу работать : заставить Git распознавать переименование, создав подкаталог и переместив в него содержимое.
Вернитесь в репозиторий «A» и получите и объедините содержимое «B»:
Чтобы показать, что они теперь объединены:
Чтобы доказать, что полная история сохраняется в связанной цепочке:
После этого мы получаем историю, но проблема в том, что если вы на самом деле храните старое репо «b» и время от времени сливаетесь с ним (скажем, на самом деле это стороннее репо, поддерживаемое отдельно), у вас проблемы, поскольку эта третья сторона переименовать не стал. Вы должны попытаться объединить новые изменения в свою версию b с переименованием, и я боюсь, что это не пройдет гладко. Но если b уйдет, вы выиграете.
источник
git log --stat
). Также я не заметил--follow
переключателя в документации git log; кажется очень удобным с переименованием. Большое спасибо за столь подробный и информативный ответ!git
этого продукта,fatal: refusing to merge unrelated histories
поэтому вы должны запускать егоgit merge -s ours --allow-unrelated-histories --no-commit B/master
.git-subtree
- это сценарий, предназначенный именно для этого варианта использования объединения нескольких репозиториев в один с сохранением истории (и / или разделения истории поддеревьев, хотя это, похоже, не имеет отношения к этому вопросу). Он распространяется как часть дерева git, начиная с выпуска 1.7.11 .Чтобы объединить репозиторий
<repo>
при ревизии в<rev>
качестве подкаталога<prefix>
, используйтеgit subtree add
следующее:git-subtree реализует стратегию слияния поддеревьев более удобным для пользователя способом.
обратная сторона является то , что в объединенном истории эти файлы без префикса (не в подкаталоге). Скажем, вы объединяете репозиторий
a
вb
. В результатеgit log a/f1
вы увидите все изменения (если они есть), кроме тех, что были в объединенной истории. Ты можешь сделать:но при этом не будут отображаться другие изменения, кроме объединенной истории.
Другими словами, если вы не измените
a
файлы в репозиторииb
, вам нужно указать--follow
и путь без префикса. Если вы измените их в обоих репозиториях, то у вас будет 2 команды, ни одна из которых не отображает все изменения.Подробнее об этом здесь .
источник
<prefix>
. Например, чтобы объединить подкаталог, который когда-то был перемещен вручную, в его собственный репозиторий, и вы хотите объединить его обратно.я хотел
git log -- file
работать без них--follow
.Шаг 1. Перепишите историю в исходном репозитории, чтобы она выглядела так, как будто все файлы всегда существовали в подкаталоге.
Создайте временную ветку для перезаписанной истории.
Затем используйте,
git filter-branch
как описано в разделе Как я могу переписать историю, чтобы все файлы, кроме тех, которые я уже переместил, находились в подкаталоге? :Шаг 2 : переключитесь на целевой репозиторий. Добавьте исходный репозиторий как удаленный в целевой репозиторий и получите его содержимое.
Шаг 3 : Используйте
merge --onto
для добавления коммитов перезаписанного исходного репозитория поверх целевого репозитория.Вы можете проверить журнал, чтобы убедиться, что это действительно принесло вам то, что вы хотели.
Шаг 4 : После перебазирования вы находитесь в состоянии «отключенная голова». Вы можете перемотать мастер к новой главе.
Шаг 5 : Наконец-то очистка: удалите временный пульт.
источник
git rebase
похоже, не разрешает указанные параметры вместе: "ошибка: невозможно объединить интерактивные параметры (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + - -onto) с параметрами am (--committer-date-is-author-date) »--committer-date-is-author-date
. Проверка несовместимости параметров была недавно добавлена в git v2.19.0 ( github.com/git/git/commit/… ). Судя по описанию, это звучит так, как будто--committer-date-is-author-date
раньше его молча игнорировали.filter-branch
команду, используйтеgit filter-repo --to-subdirectory-filter <dir>
ее быстрее и проще.Если вы действительно хотите сшить все вместе, ищите прививки. Вы также должны использовать
git rebase --preserve-merges --onto
. Также есть возможность сохранить дату автора для информации о коммиттере.источник
git filter-branch
и вроде работает, но может у вас лучше. Я попробую.Я нашел следующее решение, подходящее для меня. Сначала я захожу в проект B, создаю новую ветку, в которой уже все файлы будут перемещены в новый подкаталог. Затем я отправляю эту новую ветку в origin. Затем я перехожу в проект A, добавляю и получаю удаленный от B, затем проверяю перемещенную ветку, возвращаюсь в мастер и объединяю:
Если я перейду в подкаталог
subdir
, я могу использоватьgit log --follow
и все еще иметь историю.Я не эксперт по git, поэтому не могу комментировать, является ли это особенно хорошим решением или в нем есть оговорки, но пока все в порядке.
источник
Вы пробовали добавить дополнительный репозиторий как подмодуль git? Он не будет объединять историю с содержащим его репозиторием, фактически, это будет независимый репозиторий.
Я упоминаю об этом, потому что вы этого не сделали.
источник
Допустим , вы хотите объединить репозиторий
a
вb
(я предполагаю , что они расположены рядом друг с другом):Для этого вам необходимо
git-filter-repo
установить (filter-branch
не рекомендуется ).Пример слияния двух больших репозиториев, поместив один из них в подкаталог: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
Подробнее об этом здесь .
источник
Подобно ответу hfs, я хотел
git log -- file
работать без них--follow
.Однако я выбрал более современный
filter-repo
(при условии, чтоnew
репо существует и проверено):вам может потребоваться исправить конфликты (вручную) или изменить команду rebase, чтобы включить ее,
--merge -s recursive -X theirs
если вы хотите попробовать решить ее с помощьюtheirs
версии:вы попадаете на отдельную HEAD, поэтому создайте новую ветку и объедините ее с основным примечанием, что современные репозитории не должны использовать «главную» ветвь, а «главную»
уборка
источник