我一直在为同样的问题苦苦挣扎。另一个答案中提到的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:如果您的存储库很大,比如说几 GB,我发现了一个很好的选择,可以将转储文件拆分为较小的文件(每个文件仅包含几百个修订版),然后再将它们拆分为单独的修订版。