Я боролся с той же проблемой в течение времени. SVN merge script, упомянутый в другом ответе, явно говорит о том, что ему не рекомендуется объединять большие и независимые репозитории (что бывает в моем случае).
Решение, которое я нашел, состояло в том, чтобы разделить материалы из обоих хранилищ и отсортировать их по дате, а затем загрузить каждую отдельную заявку отдельно в новый репозиторий.
Создание файлов дампа (они имеют расширение .out
, чтобы избежать конфликтов с помощью инструмента сортировки используется позже).
svnadmin dump \path\to\repoA > repoA.out
svnadmin dump \path\to\repoB > repoB.out
Разделить файлы дампа на отдельные изменения. Для этого я использовал svndumptool (упомянутый на веб-странице вышеупомянутого скрипта слияния). Синтаксис: svndumptool split src_file start_rev end_rev tgt_file
. К сожалению, он извлекает ревизии по одному диапазону за раз. Чтобы преодолеть это, вы можете использовать следующий пакетный скрипт:
REM split.bat
for /L %%I in (%2, 1, %3) do (
svndumptool split %1 %%I %%I %4.%%I.dump
)
Синтаксис будет тогда:
split repoA.out 0 1000 repoA
split repoB.out 0 2000 repoB
Он будет генерировать набор .dump
файлов.
Я использовал программу облицованный в конце ответа (я назвал его svn_merge_by_date
) сортировать по дате изменения, и загрузить их в новое хранилище соответственно: svn_merge_by_date new_repo_name
.
В моем случае хранилища были полностью независимы друг от друга, поэтому ни один каталог не имел то же имя. Если это ваш случай, было бы безопаснее отслеживать исходный репозиторий и загружать его в другой каталог. Каждый файл дампа содержит UUID репозитория, чтобы вы могли их использовать.
С этим вы сохраняете как историю, так и ревизии, также сортируются по времени.
Код для svn_merge_by_date
. Он находится на C++ и требует, чтобы Boost скомпилировал его. В основном он будет сканировать все файлы .dump
в текущем каталоге, сортировать их по дате ревизии и загружать в новый репозиторий (первый параметр командной строки).
// DISCLAIMER: This code has been developed to solve a very specific
// and one-time problem and it is given AS IS.
#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
void get_all(const fs::path& root, const std::string& ext, std::vector<fs::path>& ret)
{
if (!fs::exists(root) || !fs::is_directory(root)) return;
fs::recursive_directory_iterator it(root), endit;
while (it != endit) {
if (fs::is_regular_file(*it) && it->path().extension() == ext) ret.push_back(it->path().filename());
++it;
}
}
std::string get_date(const fs::path& filename)
{
std::ifstream f(filename.string());
if (f) {
std::string line;
while (std::getline(f, line)) {
if (line == "svn:date") { // date is two lines below
std::getline(f, line);
std::getline(f, line);
return line;
}
}
}
return "";
}
int main(int argc, char* argv[])
{
if (argc < 2) return 0;
const std::string svn_path(argv[1]);
std::vector<fs::path> filenames;
get_all(".", ".dump", filenames);
std::vector<std::pair<std::string, fs::path>> sorted_files;
for (auto it = filenames.begin(); it != filenames.end(); ++it) {
const auto date = get_date(*it);
if (!date.empty()) {
sorted_files.push_back(std::make_pair(date, *it));
}
}
std::sort(sorted_files.begin(), sorted_files.end());
for (auto it = sorted_files.begin(); it != sorted_files.end(); ++it) {
std::cout << it->first << " -> " << it->second << std::endl;
const auto cmd = std::string("svnadmin load ") + svn_path + " < " + it->second.string();
system(cmd.c_str());
}
return 0;
}
PS: если хранилище велико, скажем, несколько гигабайтов, я нашел хорошую возможность разделить дамп-файлы в файлы меньшего размера (содержащие только несколько сотен изменений каждый), прежде чем продолжить разделить их на отдельные изменения.
Возможно, да. Это должно быть возможным благодаря svndump-ing обоих хранилищам; вам придется изменить пути в каждом дампе, а затем, возможно, закрепить их вместе в порядке фиксации, убедившись, что вы обновите любые ссылки на метаданные, чтобы фиксировать числа, которые вы меняете, такие как svn: merge-info, затем svn load в новый репозиторий. (И это «ветви» с «е».) – Rup