所以目前我们的项目在他们自己的仓库中,但我们想改变它,以便项目在一个仓库下。所以目前我们有:
- 回购协议
- 树干
- 分支机构
- 回购B
- 树干
- 分支机构
- ...
我们要:
- 树干
- 回购协议
- 回购B
- ...
- 分支机构
- 回购协议
- 回购B
- ...
我遇到的真正问题是我们希望新仓库中的提交按日期顺序排列。
我是否必须制作新的回购并将所有项目加载到其中,以便他们获得新的转速。然后以某种方式将提交移动到具有日期排序的第二个新仓库?
因此,任何帮助我如何实现对组合回购的提交的排序将不胜感激。
谢谢
所以目前我们的项目在他们自己的仓库中,但我们想改变它,以便项目在一个仓库下。所以目前我们有:
我们要:
我遇到的真正问题是我们希望新仓库中的提交按日期顺序排列。
我是否必须制作新的回购并将所有项目加载到其中,以便他们获得新的转速。然后以某种方式将提交移动到具有日期排序的第二个新仓库?
因此,任何帮助我如何实现对组合回购的提交的排序将不胜感激。
谢谢
这里有两个问题。首先,要合并转储文件以使转速按日期顺序排列,您可以使用此工具(它对我有用)。但是,正如上面评论中所指出的,由于转速数的变化,您可能会遇到问题(例如,我不知道该工具是否处理 svn:merginfo 属性)。
其次,重新排列路径名比较棘手。您需要更改转储文件中的路径名。我用这个 perl 模块来做这种事情。
但更简单的答案是将转储文件加载到一个新的存储库中,如下所示:
svnadmin dump -q repoA | svnadmin load --parent-dir repoA mergedrepos
svnadmin dump -q repoB | svnadmin load --parent-dir repoB mergedrepos
是的,修订日期会出现问题,但我已经这样做了很多次,到目前为止还没有给我或我的用户带来任何问题。当您在 repoA 或 repoB 中使用 svn log of files 进行查询时,日期将按顺序排列,只有当文件在两者之间移动,或者您在整个存储库上运行 svn log 时,才会出现顺序问题。
一旦你加载了两个存储库,你可以将东西移动到你想要的结构中,例如
svn mv file:///svn/mergedrepos/repoA/trunk file:///svn/mergedrepos/trunk/repoA
请注意,您可能必须在加载和 mv 命令之前创建目录,但这留给读者作为练习。
(它是带有“e”的“分支”。)
是的,我知道它是分支,在我们的 svn 中也是如此。:)
特伦特:谢谢你的信息,我想它会像你告诉我的那样工作。所以我写了一个脚本,将项目组合成一个。
我知道只有在查看主干时,历史才会看起来很有趣,但好心的希望是提交将按日期排序。我还没有真正弄清楚如何按日期对提交进行排序。那么有谁知道我如何将提交整理成日期顺序?
编辑:看起来像mergeepo脚本会让我很容易地进行排序和合并
我一直在为同样的问题苦苦挣扎。另一个答案中提到的SVN 合并脚本明确表示不鼓励合并大型独立存储库(这恰好是我的情况)。
我找到的解决方案是将来自两个存储库的提交拆分并按日期对它们进行排序,然后将每个单独的提交分别加载到新存储库中。
创建转储文件(它们具有.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,我找到了一个很好的选择,可以将转储文件拆分为较小的文件(每个文件仅包含几百个修订版),然后再将它们拆分为单独的修订版。