code: func reachableObjects(
  	commit *object.Commit,
  	seen map[plumbing.Hash]bool,
  	visited map[plumbing.Hash]bool,
  	ignore []plumbing.Hash,
  	cb func(h plumbing.Hash),
  ) error {
  	i := object.NewCommitPreorderIter(commit, seen, ignore)
  	pending := make(map[plumbing.Hash]bool)
  	addPendingParents(pending, visited, commit)
  	for {
  		commit, err := i.Next()
  		if err == io.EOF {
  			break
  		}
  
  		if err != nil {
  			return err
  		}
  
  		if pending[commit.Hash] {
  			delete(pending, commit.Hash)
  		}
  
  		addPendingParents(pending, visited, commit)
  
  		if visited[commit.Hash] && len(pending) == 0 {
  			break
  		}
  
  		if seen[commit.Hash] {
  			continue
  		}
  
  		cb(commit.Hash)
  
  		tree, err := commit.Tree()
  		if err != nil {
  			return err
  		}
  
  		if err := iterateCommitTrees(seen, tree, cb); err != nil {
  			return err
  		}
  	}
  
  	return nil
  }
docs: // reachableObjects returns, using the callback function, all the reachable
  // objects from the specified commit. To avoid to iterate over seen commits,
  // if a commit hash is into the 'seen' set, we will not iterate all his trees
  // and blobs objects.