使用 LibGit2Sharp 编辑旧的提交信息

Edit old commit messages using LibGit2Sharp

是否可以使用 libgit2sharp 编辑不是最新提交的提交消息?

git filter-branch的类比是Repository.Refs.RewriteHistory

例如,让我们通过将 foo 替换为 Whosebug:

来重写所有包含 foo 的提交消息
repo.Refs.RewriteHistory (new RewriteHistoryOptions {
    OnError = OnError, 
    OnSucceeding = OnSucceeding,
    CommitHeaderRewriter = c =>
    CommitRewriteInfo.From (c, c.Message.Replace ("foo", "Whosebug")),
}, commitsToRewrite);   

预重写:

git log --oneline
b859690 Commit foo 3
327f702 Commit foo 2
75ac0b8 Commit foo 1

Post-重写:

git log --oneline
dc156e3 Commit Whosebug 3
587f6c3 Commit Whosebug 2
894361f Commit Whosebug 1

注意: 正如您将在上面的日志输出中看到的那样,SHA 已更改,就像它们通过 git filter-branch 一样,因此您必须 force 对遥控器的任何推送...

我会高度推荐通过测试夹具FilterBranchFixture.cs,因为这是RewriteHistory的最佳文档,你会发现不同的重写类,比如重写提交的父项,在这里使用以及如何处理错误...

WARNING! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM REBASE" section in git-rebase(1) for further information about rewriting published history.)

Cut/Paste 示例:

using System;
using LibGit2Sharp;

namespace gitrewrite
{

    class MainClass
    {
        private static bool succeeding;
        private static Exception error;

        public static void Main (string[] args)
        {
            var repo = new Repository ("/Users/sushi/code/XamTests/RepoTestBed");

            // Assuming you might pre-filter, but for this example take ALL commits
            var commitsToRewrite = repo.Commits;

            repo.Refs.RewriteHistory (new RewriteHistoryOptions {
                OnError = OnError, 
                OnSucceeding = OnSucceeding,
                CommitHeaderRewriter = c =>
                    CommitRewriteInfo.From (c, c.Message.Replace ("foo", "Whosebug")),
            }, commitsToRewrite);   
        }

        private static Action OnSucceeding {
            get {
                succeeding = false;
                return () => succeeding = true;
            }
        }

        private static Action<Exception> OnError {
            get {
                error = null;
                return ex => error = ex;
            }
        }
    }
}