code: func walkGraph(result *[]*object.Commit, seen *map[plumbing.Hash]struct{}, current *object.Commit, path string) error {
  	// check and update seen
  	if _, ok := (*seen)[current.Hash]; ok {
  		return nil
  	}
  	(*seen)[current.Hash] = struct{}{}
  
  	// if the path is not in the current commit, stop searching.
  	if _, err := current.File(path); err != nil {
  		return nil
  	}
  
  	// optimization: don't traverse branches that does not
  	// contain the path.
  	parents, err := parentsContainingPath(path, current)
  	if err != nil {
  		return err
  	}
  	switch len(parents) {
  	// if the path is not found in any of its parents, the path was
  	// created by this commit; we must add it to the revisions list and
  	// stop searching. This includes the case when current is the
  	// initial commit.
  	case 0:
  		*result = append(*result, current)
  		return nil
  	case 1: // only one parent contains the path
  		// if the file contents has change, add the current commit
  		different, err := differentContents(path, current, parents)
  		if err != nil {
  			return err
  		}
  		if len(different) == 1 {
  			*result = append(*result, current)
  		}
  		// in any case, walk the parent
  		return walkGraph(result, seen, parents[0], path)
  	default: // more than one parent contains the path
  		// TODO: detect merges that had a conflict, because they must be
  		// included in the result here.
  		for _, p := range parents {
  			err := walkGraph(result, seen, p, path)
  			if err != nil {
  				return err
  			}
  		}
  	}
  	return nil
  }
docs: // Recursive traversal of the commit graph, generating a linear history of the
  // path.