RewriteHistory.OnComplete

Had cause to actually use RewriteHistory tonight to purge some passwords that should never have been pushed. Two proposed enhancements came out of that hacking:

* `OnComplete` action: Until I was ready to pull the trigger on the actual rewrite, I found it quite handy to be able to verify that I was on the right track but then throw to rollback and continue development.

  Using this on every test case is probably overkill, but I couldn't decide where to stop.
* My desired behavior was essentially "inject cleansed file from a branch" into earlier trees. Without `TreeEntryDefinition.From(te)`, I have to do something like:

  ```csharp
  var blob = (Blob)te.Target;
  td.Add(te.Path, blob, blob.Mode);
  ```

  Not a huge deal, but I resent the extra work. Things would get even more complicated if you're dealing with more than one type of `TreeEntry`.

For posterity, here's a simplified version of the rewrite code I ended up with:

```csharp
var clean = repo.Branches["clean"];
var todo = new[]
{
    clean[@"file1"],
    clean[@"file2"],
    clean[@"file3"],
};

repo.Refs.RewriteHistory(
    new RewriteHistoryOptions
    {
        CommitTreeRewriter =
            c =>
            {
                var td = TreeDefinition.From(c);

                foreach (var te in todo)
                    if (td[te.Path] != null)
                        td.Add(te.Path, TreeEntryDefinition.From(te));

                return td;
            },
        PruneEmptyCommits = true,
        OnComplete =
            () =>
            {
                foreach (var te in todo)
                {
                    Console.WriteLine("=== {0} ===", te.Path);
                    Console.WriteLine(((Blob)repo.Head[te.Path].Target).ContentAsText());
                }

                throw new Exception("Forcing rollback");
            },
    }, repo.Commits.QueryBy(new CommitFilter { Since = repo.Refs }));
```