func (b *blame) fillGraphAndData() error {
	b.graph = make([][]*object.Commit, len(b.revs))
	b.data = make([]string, len(b.revs))  
	for i, rev := range b.revs {
		file, err := rev.File(b.path)
		if err != nil {
			return nil
		}
		b.data[i], err = file.Contents()
		if err != nil {
			return err
		}
		nLines := countLines(b.data[i])
		b.graph[i] = make([]*object.Commit, nLines)
		if i == 0 {
			for j := 0; j < nLines; j++ {
				b.graph[i][j] = (*object.Commit)(b.revs[i])
			}
		} else {
			b.assignOrigin(i, i-1)
		}
	}
	return nil
}
build graph of a file from its revision history
package git
import (
	"bytes"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"unicode/utf8"
	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/object"
	"gopkg.in/src-d/go-git.v4/utils/diff"
)
type BlameResult struct {
	Path string
	Rev plumbing.Hash
	Lines []*Line
}
func Blame(c *object.Commit, path string) (*BlameResult, error) {
	b := new(blame)
	b.fRev = c
	b.path = path
	if err := b.fillRevs(); err != nil {
		return nil, err
	}
	if err := b.fillGraphAndData(); err != nil {
		return nil, err
	}
	file, err := b.fRev.File(b.path)
	if err != nil {
		return nil, err
	}
	finalLines, err := file.Lines()
	if err != nil {
		return nil, err
	}
	lines, err := newLines(finalLines, b.sliceGraph(len(b.graph)-1))
	if err != nil {
		return nil, err
	}
	return &BlameResult{
		Path:  path,
		Rev:   c.Hash,
		Lines: lines,
	}, nil
}
type Line struct {
	Author string
	Text string
}
func newLine(author, text string) *Line {
	return &Line{
		Author: author,
		Text:   text,
	}
}
func newLines(contents []string, commits []*object.Commit) ([]*Line, error) {
	if len(contents) != len(commits) {
		return nil, errors.New("contents and commits have different length")
	}
	result := make([]*Line, 0, len(contents))
	for i := range contents {
		l := newLine(commits[i].Author.Email, contents[i])
		result = append(result, l)
	}
	return result, nil
}
type blame struct {
	path string
	fRev *object.Commit
	revs []*object.Commit
	data []string
	graph [][]*object.Commit
}
func (b *blame) fillRevs() error {
	var err error
	b.revs, err = references(b.fRev, b.path)
	return err
}