libgit2 / libgit2/libgit2sharp

RewriteHistory extremely slow

オープン
#1,684 コメント 6 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
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. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず、3,000 件以上のコミットを含むリポジトリで報告を再現し、「Rewrite history started」から最初の CommitTreeRewriter callback までの遅延を測定します。issue に示されている RewriteHistory の呼び出しと CommitTreeRewriter のセットアップを調査します。報告されている pruning の動作を維持したまま、同じ履歴の書き換えが数時間ではなく数分で完了すれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
csharp, git
領域
devtools, performance
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。