У меня есть Git-репозиторий в папке с именем XXX , и у меня есть второй Git-репозиторий с именем YYY .
Я хочу импортировать репозиторий XXX в репозиторий YYY в качестве подкаталога с именем ZZZ и добавить всю историю изменений XXX в YYY .
Структура папок перед:
├── XXX
│ ├── .git
│ └── (project files)
└── YYY
├── .git
└── (project files)
Структура папок после:
YYY
├── .git <-- This now contains the change history from XXX
├── ZZZ <-- This was originally XXX
│ └── (project files)
└── (project files)
Можно ли это сделать, или я должен использовать субмодули?
Ответы:
Вероятно, самым простым способом было бы перетащить материал XXX в ветку в YYY, а затем объединить его с master:
В ГГГ :
Я просто попробовал это с парой моих репозиториев, и это работает. В отличие от ответа Йорга, он не позволит вам продолжать использовать другой репозиторий, но я не думаю, что вы указали это в любом случае.
Примечание: так как это было изначально написано в 2009 году, git добавил слияние поддеревьев, упомянутое в ответе ниже. Я бы, вероятно, использовал этот метод сегодня, хотя, конечно, этот метод все еще работает.
источник
git mv $(ls|grep -v <your foldername>) <your foldername>/
это скопирует все файлы и папки в вашу новую папкуЕсли вы хотите сохранить точную историю коммитов второго репозитория и, следовательно, также сохранить возможность легко объединять восходящие изменения в будущем, то вот метод, который вам нужен. Это приводит к тому, что в ваше хранилище импортируется немодифицированная история поддерева плюс один коммит слияния для перемещения объединенного репозитория в подкаталог.
Вы можете отслеживать восходящие изменения, например, так:
Git сам определяет, где находятся корни, прежде чем выполнять слияние, поэтому вам не нужно указывать префикс при последующих слияниях.
Недостатком является то , что в объединенном истории эти файлы без префикса (не в подкаталоге). В результате
git log ZZZ/a
вам покажут все изменения (если они есть), кроме тех, что в объединенной истории. Ты можешь сделать:но это не покажет изменения, отличные от истории слияния.
Другими словами, если вы не измените
ZZZ
файлы в хранилищеXXX
, вам нужно указать--follow
и путь без префикса. Если вы измените их в обоих репозиториях, то у вас есть 2 команды, ни одна из которых не отображает все изменения.Git версии до 2.9 : вам не нужно передавать эту
--allow-unrelated-histories
опциюgit merge
.Метод в другом ответе, который использует
read-tree
и пропускаетmerge -s ours
шаг, практически не отличается от копирования файлов с помощью cp и фиксации результата.Первоначальный источник был взят из справочной статьи github "Слияние поддеревьев" . И еще одна полезная ссылка .
источник
git log
один из файлов, которые я извлек, я просто увижу один коммит слияния и ничего из его предыдущей жизни в другом репо? Git 1.8.0git log -- myfile
вместоgit log -- rack/myfile
--allow-unrelated-histories
при слиянии.git-subtree
скрипт, предназначенный именно для этого случая использования объединения нескольких репозиториев в одно при сохранении истории (и / или разбиения истории поддеревьев, хотя это, похоже, не имеет отношения к этому вопросу). Он распространяется как часть дерева мерзавцев с версии 1.7.11 .Чтобы объединить репозиторий
<repo>
с ревизией<rev>
как подкаталог<prefix>
, используйтеgit subtree add
следующее:git-subtree реализует стратегию слияния поддеревьев более удобным для пользователя способом.
Для вашего случая внутри репозитория YYY вы должны выполнить:
Недостатком является то , что в объединенном истории эти файлы без префикса (не в подкаталоге). В результате
git log ZZZ/a
вам покажут все изменения (если они есть), кроме тех, что в объединенной истории. Ты можешь сделать:но это не покажет изменения, отличные от истории слияния.
Другими словами, если вы не меняете
ZZZ
файлы в хранилищеXXX
, вам нужно указать--follow
и путь без префикса. Если вы измените их в обоих репозиториях, то у вас есть 2 команды, ни одна из которых не отображает все изменения.Подробнее об этом здесь .
источник
git subtree add -P name-of-desired-prefix ~/location/of/git/repo-without-.git branch-name
Существует хорошо известный пример этого в самом Git-репозитории, который в сообществе Git известен как « самое крутое слияние за всю историю » (после строки темы, которую Линус Торвальдс использовал в электронном письме к списку рассылки Git, который описывает это слияния). В этом случае
gitk
графический интерфейс Git, который теперь является частью собственно Git, фактически был отдельным проектом. Линусу удалось объединить этот репозиторий с репозиторием Git таким образом, чтобыgit pull
редактируются.Электронное письмо содержит шаги, необходимые для воспроизведения, но это не для слабонервных: во-первых, Линус написал Git, поэтому он, вероятно, знает об этом немного больше, чем вы или я, и во-вторых, это было почти 5 лет назад и Гит улучшилась значительно с тех пор, так что, может быть , теперь гораздо проще.
В частности, я думаю, что в настоящее время можно использовать подмодуль gitk, в этом конкретном случае.
источник
git-subtree
инструмент стороннего производителя, который может помочь вам в этом: github.com/apenwarr/git-subtreesubtree
Стратегия слияния, особенно в сочетании сgit-subtree
инструментом является хорошей, может быть , даже лучшей альтернативой подмодулей.Простой способ сделать это - использовать git format-patch.
Предположим, у нас есть 2 репозитория git foo и bar .
foo содержит:
Бар содержит:
и мы хотим получить foo, содержащий историю баров и эти файлы:
Итак, чтобы сделать это:
И если мы хотим переписать все коммиты сообщений из bar, которые мы можем сделать, например, в Linux:
Это добавит «[bar]» в начале каждого сообщения коммита.
источник
git am
скорее всего произойдет сбой.[ ]
из сообщения коммита. Таким образом, вы должны использовать другой маркер, чем[bar]
Эта функция клонирует удаленное репо в локальный каталог репо, после объединения все коммиты будут сохранены,
git log
будут показаны исходные коммиты и правильные пути:Как пользоваться:
Если вы сделаете небольшие изменения, вы даже можете переместить файлы / каталоги объединенного репо по разным путям, например:
Notices
Paths заменяется на via
sed
, поэтому после слияния убедитесь, что он перемещен по правильным путям. Параметр существует только с Git> = 2.9.--allow-unrelated-histories
источник
gnu-sed
чтобы заставитьgit-add-repo
функцию работать. Еще раз спасибо, Андрей!На основании этой статьи , использование поддерева - это то, что мне помогло, и была перенесена только соответствующая история. Публикация здесь на случай, если кому-то понадобятся шаги (не забудьте заменить заполнители на значения, применимые к вам):
в вашем исходном репозитории разделить подпапку на новую ветку
git subtree split --prefix=<source-path-to-merge> -b subtree-split-result
в месте назначения слияния репо в ветке результатов разделения
проверить ваши изменения и зафиксировать
Не забудь
Очистить, удалив
subtree-split-result
веткуgit branch -D subtree-split-result
Удалите пульт, который вы добавили, чтобы получить данные из репозитория
git remote rm merge-source-repo
источник
Добавив еще один ответ, я думаю, что это немного проще. Извлечение repo_dest выполняется в repo_to_import, а затем выполняется push -set-upstream url: repo_dest master.
Этот метод помог мне импортировать несколько небольших репо в большее.
Как импортировать: repo1_to_import в repo_dest
Переименуйте или переместите файлы и каталоги в нужное место в исходном репо перед выполнением импорта. например
Метод, описанный по следующей ссылке, вдохновил этот ответ. Мне понравилось это, поскольку это казалось более простым. Но остерегайтесь! Там будут драконы! https://help.github.com/articles/importing-an-external-git-repository
git push --mirror url:repo_dest
отправляет историю и состояние локального репо в удаленный режим (url: repo_dest). НО это удаляет старую историю и состояние удаленного. Веселье наступает! : -Eисточник
Я хотел импортировать только некоторые файлы из другого хранилища (XXX) в моем случае. Поддерево было слишком сложным для меня, и другие решения не работали. Вот что я сделал:
Это дает вам разделенный пробелами список всех коммитов, которые влияют на файлы, которые я хотел импортировать (ZZZ) в обратном порядке (вам может понадобиться добавить --follow, чтобы также перехватывать переименования). Затем я зашел в целевой репозиторий (YYY), добавил другой репозиторий (XXX) как удаленный, сделал выборку из него и, наконец,:
который добавляет все коммиты в вашу ветку, поэтому вы будете иметь все файлы с их историей и можете делать с ними все, что захотите, как если бы они всегда были в этом хранилище.
источник
Посмотрите Базовый пример в этой статье и рассмотрите такое отображение в репозиториях:
A
<->YYY
,B
<->XXX
После всех действий, описанных в этой главе (после слияния), удалите ветку
B-master
:Затем нажмите изменения.
Меня устраивает.
источник
Я был в ситуации, когда искал,
-s theirs
но, конечно, такой стратегии не существует. Моя история заключалась в том, что я создал проект на GitHub, и теперь по какой-то причине мой локальныйmaster
ресурс не может быть объединен сupstream/master
хотя я не внес никаких локальных изменений в эту ветку. (Действительно, не знаю, что там произошло - наверное, вверх по течению были сделаны какие-то грязные толчки за кулисами, может быть?)То, что я закончил, было
Так что теперь my
master
снова синхронизированupstream/master
(и вы можете повторить вышеописанное для любой другой ветви, которую вы также хотите синхронизировать аналогично).источник
git reset --hard upstream/master
в вашем местномmaster
отделении сделают эту работу. Таким образом, вы не потеряете локальную ветку - такие вещи, как восходящий поток по умолчанию.Я могу предложить другое решение (альтернативу git-submodules ) для вашей проблемы - инструмент gil (git links)
Это позволяет описывать и управлять сложными зависимостями git-репозиториев.
Также он предоставляет решение проблемы зависимостей git recursive submodules .
Предположим, у вас есть следующие зависимости проекта: пример графика зависимостей репозитория git
Затем вы можете определить
.gitlinks
файл с описанием отношений с репозиториями:Каждая строка описывает git ссылку в следующем формате:
Наконец, вы должны обновить ваш корневой репозиторий с примерами:
В результате вы будете клонировать все необходимые проекты и правильно связать их друг с другом.
Если вы хотите зафиксировать все изменения в каком-либо репозитории со всеми изменениями в дочерних связанных репозиториях, вы можете сделать это с помощью одной команды:
Команды Pull, Push работают аналогично:
Инструмент Gil (git links) поддерживает следующие команды:
Подробнее о проблеме зависимости git рекурсивных субмодулей .
источник
Позвольте мне использовать имена
a
(вместоXXX
иZZZ
) иb
(вместоYYY
), поскольку это немного облегчает чтение описания.Допустим , вы хотите объединить репозиторий
a
вb
(я предполагаю , что они расположены рядом друг с другом):Для этого вам нужно
git-filter-repo
установить (filter-branch
не рекомендуется ).Пример объединения двух больших репозиториев и помещения одного из них в подкаталог: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
Подробнее об этом здесь .
источник
Я не знаю простого способа сделать это. Вы МОЖЕТЕ сделать это:
Я могу редактировать с деталями, если это звучит привлекательно.
источник
Я думаю, что вы можете сделать это, используя «git mv» и «git pull».
Я честный мерзавец, так что будьте осторожны с вашим основным хранилищем, но я только что попробовал это в временном каталоге, и это, похоже, работает.
Сначала - переименуйте структуру XXX, чтобы она соответствовала тому, как вы хотите, чтобы она выглядела, когда она находится в пределах YYY:
Теперь XXX выглядит так:
Теперь используйте 'git pull', чтобы получить изменения:
Теперь YYY выглядит так:
источник