libgit2 / libgit2/libgit2sharp

RewriteHistory extremely slow

未關閉
#1,684 6 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

主要語言
C#
星號
3.5k
分支
925
PR 合併指標
30 天內沒有已合併 PR

描述

Reproduction steps

Find a repo with 3000+ commits
Run the below code against that repo to rewrite the repo history:

private static void RewriteHistory(string repoPath, ICollection<string> subFolders)
{
    using (var repo = new Repository(repoPath))
    {
        var refs = repo.Refs.Where(r => r.CanonicalName.EndsWith("develop")).OrderBy(r => r.CanonicalName).ToList();
        var commits = repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = refs }).ToArray();
        var count = 0;
        var stopwatch = Stopwatch.StartNew();

        Logger.InfoFormat("Found {0} commits", commits.Length);
        Logger.InfoFormat("Rewrite history started");

        repo.Refs.RewriteHistory(new RewriteHistoryOptions
        {
            OnError = OnError,
            OnSucceeding = OnSucceeding,
            PruneEmptyCommits = true,
            CommitTreeRewriter = commit =>
            {
                Logger.InfoFormat("Commit {0}/{1}", ++count, commits.Length);

                var tree = TreeDefinition.From(commit);
                foreach (var treeEntry in commit.Tree)
                {
                    var match = subFolders.FirstOrDefault(s => treeEntry.Path.StartsWithIgnoreCase(s));

                    if (match == null)
                        tree.Remove(treeEntry.Path);
                }

                return tree;
            }
        }, commits);
        Logger.InfoFormat("Rewrite history ended. Took {0}", stopwatch.Elapsed);

        repo.Reset(ResetMode.Hard, repo.Head.Commits.First());
    }
}
Expected behavior

This should take a reasonable time. I expect it to take a few minutes for sure but not hours. For example when running something similar in git from the command like it takes minutes. I'm sorry I don't have specific times but I can try to provide more data to compare performance if necessary.

Actual behavior

This takes 1h 43 minutes of which 1h 40 to just start the rewrite and about a couple of minutes to go through all the commits.
INFO : Found 3486 commits
INFO : Rewrite history started
[between these two log messages there is a 1h 40m gap]
INFO : Commit 1/3486
INFO : Commit 2/3486
...
INFO : Rewrite history ended. Took 01:43:51.5536779

Version of LibGit2Sharp (release number or SHA1)

0.26.0 + 2.0.267 (native)

Operating system(s) tested; .NET runtime tested

.net 4.6.1 - Win 2012R2

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

首先,使用包含 3,000 多個提交的 repository 重現該報告,並測量「Rewrite history started」與第一個 CommitTreeRewriter callback 之間的延遲。檢查 issue 中顯示的 RewriteHistory 呼叫及其 CommitTreeRewriter 設定。當相同的歷史重寫在幾分鐘而不是幾小時內完成,同時保留報告中的 pruning 行為時,即表示完成。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
csharp, git
領域
devtools, performance
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。