First round of mass keep-alive additions
diff --git a/blame.go b/blame.go
index b07d6bc..de32bb3 100644
--- a/blame.go
+++ b/blame.go
@@ -76,6 +76,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_blame_file(&blamePtr, v.ptr, cpath, copts)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -88,11 +89,15 @@
 }
 
 func (blame *Blame) HunkCount() int {
-	return int(C.git_blame_get_hunk_count(blame.ptr))
+	ret := int(C.git_blame_get_hunk_count(blame.ptr))
+	runtime.KeepAlive(blame)
+
+	return ret
 }
 
 func (blame *Blame) HunkByIndex(index int) (BlameHunk, error) {
 	ptr := C.git_blame_get_hunk_byindex(blame.ptr, C.uint32_t(index))
+	runtime.KeepAlive(blame)
 	if ptr == nil {
 		return BlameHunk{}, ErrInvalid
 	}
@@ -101,6 +106,7 @@
 
 func (blame *Blame) HunkByLine(lineno int) (BlameHunk, error) {
 	ptr := C.git_blame_get_hunk_byline(blame.ptr, C.size_t(lineno))
+	runtime.KeepAlive(blame)
 	if ptr == nil {
 		return BlameHunk{}, ErrInvalid
 	}
diff --git a/blob.go b/blob.go
index 73a4a19..5235597 100644
--- a/blob.go
+++ b/blob.go
@@ -21,13 +21,19 @@
 }
 
 func (v *Blob) Size() int64 {
-	return int64(C.git_blob_rawsize(v.cast_ptr))
+	ret := int64(C.git_blob_rawsize(v.cast_ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Blob) Contents() []byte {
 	size := C.int(C.git_blob_rawsize(v.cast_ptr))
 	buffer := unsafe.Pointer(C.git_blob_rawcontent(v.cast_ptr))
-	return C.GoBytes(buffer, size)
+
+	goBytes := C.GoBytes(buffer, size)
+	runtime.KeepAlive(v)
+
+	return goBytes
 }
 
 func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) {
@@ -53,6 +59,7 @@
 	}
 
 	ecode := C.git_blob_create_frombuffer(&id, repo.ptr, unsafe.Pointer(&data[0]), size)
+	runtime.KeepAlive(repo)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -102,16 +109,18 @@
 		return nil, MakeGitError(ecode)
 	}
 
-	return newBlobWriteStreamFromC(stream), nil
+	return newBlobWriteStreamFromC(stream, repo), nil
 }
 
 type BlobWriteStream struct {
-	ptr *C.git_writestream
+	ptr  *C.git_writestream
+	repo *Repository
 }
 
-func newBlobWriteStreamFromC(ptr *C.git_writestream) *BlobWriteStream {
+func newBlobWriteStreamFromC(ptr *C.git_writestream, repo *Repository) *BlobWriteStream {
 	stream := &BlobWriteStream{
-		ptr: ptr,
+		ptr:  ptr,
+		repo: repo,
 	}
 
 	runtime.SetFinalizer(stream, (*BlobWriteStream).Free)
@@ -128,6 +137,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C._go_git_writestream_write(stream.ptr, ptr, size)
+	runtime.KeepAlive(stream)
 	if ecode < 0 {
 		return 0, MakeGitError(ecode)
 	}
@@ -147,6 +157,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_blob_create_fromstream_commit(&oid, stream.ptr)
+	runtime.KeepAlive(stream)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
diff --git a/branch.go b/branch.go
index d381c23..d6e7a53 100644
--- a/branch.go
+++ b/branch.go
@@ -88,6 +88,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_branch_iterator_new(&ptr, repo.ptr, refType)
+	runtime.KeepAlive(repo)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -106,6 +107,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce)
+	runtime.KeepAlive(repo)
+	runtime.KeepAlive(target)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -117,6 +120,7 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 	ret := C.git_branch_delete(b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -133,6 +137,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -145,6 +150,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_is_head(b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	switch ret {
 	case 1:
 		return true, nil
@@ -165,6 +171,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_lookup(&ptr, repo.ptr, cName, C.git_branch_t(bt))
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -179,6 +186,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_name(&cName, b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
@@ -196,6 +204,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName)
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
@@ -212,6 +221,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_set_upstream(b.Reference.ptr, cName)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -225,6 +235,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_upstream(&ptr, b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -241,6 +252,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName)
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
diff --git a/checkout.go b/checkout.go
index f5822c9..db3118f 100644
--- a/checkout.go
+++ b/checkout.go
@@ -188,6 +188,7 @@
 	defer freeCheckoutOpts(cOpts)
 
 	ret := C.git_checkout_head(v.ptr, cOpts)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -211,6 +212,7 @@
 	defer freeCheckoutOpts(cOpts)
 
 	ret := C.git_checkout_index(v.ptr, iptr, cOpts)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -226,6 +228,7 @@
 	defer freeCheckoutOpts(cOpts)
 
 	ret := C.git_checkout_tree(v.ptr, tree.ptr, cOpts)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
diff --git a/cherrypick.go b/cherrypick.go
index afc1b7e..8983a7a 100644
--- a/cherrypick.go
+++ b/cherrypick.go
@@ -66,6 +66,8 @@
 	defer freeCherrypickOpts(cOpts)
 
 	ecode := C.git_cherrypick(v.ptr, commit.cast_ptr, cOpts)
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(commit)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
diff --git a/commit.go b/commit.go
index 3ccb5da..5aa5f25 100644
--- a/commit.go
+++ b/commit.go
@@ -77,7 +77,7 @@
 func (c *Commit) TreeId() *Oid {
 	ret := newOidFromC(C.git_commit_tree_id(c.cast_ptr))
 	runtime.KeepAlive(c)
-	return c
+	return ret
 }
 
 func (c *Commit) Author() *Signature {
@@ -101,15 +101,21 @@
 		return nil
 	}
 
-	return allocCommit(cobj, c.repo)
+	parent := allocCommit(cobj, c.repo)
+	runtime.KeepAlive(c)
+	return parent
 }
 
 func (c *Commit) ParentId(n uint) *Oid {
-	return newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n)))
+	ret := newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n)))
+	runtime.KeepAlive(c)
+	return ret
 }
 
 func (c *Commit) ParentCount() uint {
-	return uint(C.git_commit_parentcount(c.cast_ptr))
+	ret := uint(C.git_commit_parentcount(c.cast_ptr))
+	runtime.KeepAlive(c)
+	return ret
 }
 
 func (c *Commit) Amend(refname string, author, committer *Signature, message string, tree *Tree) (*Oid, error) {
@@ -142,6 +148,9 @@
 	oid := new(Oid)
 
 	cerr := C.git_commit_amend(oid.toC(), c.cast_ptr, cref, authorSig, committerSig, nil, cmsg, tree.cast_ptr)
+	runtime.KeepAlive(oid)
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(tree)
 	if cerr < 0 {
 		return nil, MakeGitError(cerr)
 	}
diff --git a/config.go b/config.go
index 7408fbc..c19ad32 100644
--- a/config.go
+++ b/config.go
@@ -78,6 +78,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -94,6 +95,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_get_int32(&out, c.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
@@ -110,6 +112,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_get_int64(&out, c.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
@@ -126,7 +129,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname); ret < 0 {
+	ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname)
+	runtime.KeepAlive(c)
+	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
 	defer C.git_buf_free(&valBuf)
@@ -143,6 +148,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_get_bool(&out, c.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -162,7 +168,7 @@
 		defer C.free(unsafe.Pointer(cregexp))
 	}
 
-	iter := new(ConfigIterator)
+	iter := &ConfigIterator{cfg: c}
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
@@ -179,7 +185,7 @@
 // NewIterator creates an iterator over each entry in the
 // configuration
 func (c *Config) NewIterator() (*ConfigIterator, error) {
-	iter := new(ConfigIterator)
+	iter := &ConfigIterator{cfg: c}
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
@@ -195,7 +201,7 @@
 // NewIteratorGlob creates an iterator over each entry in the
 // configuration whose name matches the given regular expression
 func (c *Config) NewIteratorGlob(regexp string) (*ConfigIterator, error) {
-	iter := new(ConfigIterator)
+	iter := &ConfigIterator{cfg: c}
 	cregexp := C.CString(regexp)
 	defer C.free(unsafe.Pointer(cregexp))
 
@@ -221,6 +227,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_string(c.ptr, cname, cvalue)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -241,6 +248,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_int32(c.ptr, cname, C.int32_t(value))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -256,6 +264,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -271,6 +280,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_bool(c.ptr, cname, cbool(value))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -292,6 +302,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_multivar(c.ptr, cname, cregexp, cvalue)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -307,7 +318,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_delete_entry(c.ptr, cname)
-
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -323,6 +334,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_open_level(&config.ptr, parent.ptr, C.git_config_level_t(level))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(parent)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -349,6 +362,7 @@
 
 type ConfigIterator struct {
 	ptr *C.git_config_iterator
+	cfg *Config
 }
 
 // Next returns the next entry for this iterator
@@ -363,7 +377,10 @@
 		return nil, MakeGitError(ret)
 	}
 
-	return newConfigEntryFromC(centry), nil
+	entry := newConfigEntryFromC(centry)
+	runtime.KeepAlive(iter)
+
+	return entry, nil
 }
 
 func (iter *ConfigIterator) Free() {
diff --git a/describe.go b/describe.go
index d75dbcb..0b75076 100644
--- a/describe.go
+++ b/describe.go
@@ -128,6 +128,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_describe_commit(&resultPtr, c.ptr, cDescribeOpts)
+	runtime.KeepAlive(c)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -162,6 +163,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_describe_workdir(&resultPtr, repo.ptr, cDescribeOpts)
+	runtime.KeepAlive(repo)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -206,6 +208,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_describe_format(&resultBuf, result.ptr, cFormatOpts)
+	runtime.KeepAlive(result)
 	if ecode < 0 {
 		return "", MakeGitError(ecode)
 	}
diff --git a/repository.go b/repository.go
index a44b9b8..44d18a9 100644
--- a/repository.go
+++ b/repository.go
@@ -129,6 +129,7 @@
 
 func (v *Repository) SetRefdb(refdb *Refdb) {
 	C.git_repository_set_refdb(v.ptr, refdb.ptr)
+	runtime.KeepAlive(v)
 }
 
 func (v *Repository) Free() {
@@ -143,6 +144,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_config(&config.ptr, v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -158,6 +160,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_index(&ptr, v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -172,6 +175,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t))
+	runtime.KeepAlive(id)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -241,6 +245,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_repository_set_head(v.ptr, cname)
+	runtime.KeepAlive(v)
 	if ecode != 0 {
 		return MakeGitError(ecode)
 	}
@@ -252,6 +257,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_repository_set_head_detached(v.ptr, id.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(id)
 	if ecode != 0 {
 		return MakeGitError(ecode)
 	}
@@ -263,6 +270,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_head_detached(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -275,6 +283,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_head_unborn(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -286,6 +295,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_is_empty(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -298,6 +308,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_is_shallow(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -368,6 +379,9 @@
 		authorSig, committerSig,
 		nil, cmsg, tree.cast_ptr, C.size_t(nparents), parentsarg)
 
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(oid)
+	runtime.KeepAlive(parents)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -391,7 +405,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 {
+	ret := C.git_repository_odb(&odb.ptr, v.ptr)
+	runtime.KeepAlive(v)
+	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
@@ -400,15 +416,21 @@
 }
 
 func (repo *Repository) Path() string {
-	return C.GoString(C.git_repository_path(repo.ptr))
+	s := C.GoString(C.git_repository_path(repo.ptr))
+	runtime.KeepAlive(repo)
+	return s
 }
 
 func (repo *Repository) IsBare() bool {
-	return C.git_repository_is_bare(repo.ptr) != 0
+	ret := C.git_repository_is_bare(repo.ptr) != 0
+	runtime.KeepAlive(repo)
+	return ret
 }
 
 func (repo *Repository) Workdir() string {
-	return C.GoString(C.git_repository_workdir(repo.ptr))
+	s := C.GoString(C.git_repository_workdir(repo.ptr))
+	runtime.KeepAlive(repo)
+	return s
 }
 
 func (repo *Repository) SetWorkdir(workdir string, updateGitlink bool) error {
@@ -421,6 +443,7 @@
 	if ret := C.git_repository_set_workdir(repo.ptr, cstr, cbool(updateGitlink)); ret < 0 {
 		return MakeGitError(ret)
 	}
+	runtime.KeepAlive(repo)
 
 	return nil
 }
@@ -434,6 +457,7 @@
 	if ret := C.git_treebuilder_new(&bld.ptr, v.ptr, nil); ret < 0 {
 		return nil, MakeGitError(ret)
 	}
+
 	runtime.SetFinalizer(bld, (*TreeBuilder).Free)
 
 	bld.repo = v
@@ -474,7 +498,10 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	return RepositoryState(C.git_repository_state(r.ptr))
+	ret := RepositoryState(C.git_repository_state(r.ptr))
+	runtime.KeepAlive(r)
+
+	return ret
 }
 
 func (r *Repository) StateCleanup() error {
@@ -482,18 +509,22 @@
 	defer runtime.UnlockOSThread()
 
 	cErr := C.git_repository_state_cleanup(r.ptr)
+	runtime.KeepAlive(r)
 	if cErr < 0 {
 		return MakeGitError(cErr)
 	}
 	return nil
 }
+
 func (r *Repository) AddGitIgnoreRules(rules string) error {
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
 	crules := C.CString(rules)
 	defer C.free(unsafe.Pointer(crules))
-	if ret := C.git_ignore_add_rule(r.ptr, crules); ret < 0 {
+	ret := C.git_ignore_add_rule(r.ptr, crules)
+	runtime.KeepAlive(r)
+	if ret < 0 {
 		return MakeGitError(ret)
 	}
 	return nil
@@ -503,7 +534,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_ignore_clear_internal_rules(r.ptr); ret < 0 {
+	ret := C.git_ignore_clear_internal_rules(r.ptr)
+	runtime.KeepAlive(r)
+	if ret < 0 {
 		return MakeGitError(ret)
 	}
 	return nil