Detailed changes
  
  
    
    @@ -459,6 +459,7 @@ func (bug *Bug) Commit(repo repository.ClockedRepo) error {
 		return err
 	}
 
+	bug.staging.commitHash = hash
 	bug.packs = append(bug.packs, bug.staging)
 	bug.staging = OperationPack{}
 
@@ -513,9 +514,8 @@ func (bug *Bug) Merge(repo repository.Repo, other Interface) (bool, error) {
 	}
 
 	ancestor, err := repo.FindCommonAncestor(bug.lastCommit, otherBug.lastCommit)
-
 	if err != nil {
-		return false, err
+		return false, errors.Wrap(err, "can't find common ancestor")
 	}
 
 	ancestorIndex := 0
  
  
  
    
    @@ -55,7 +55,7 @@ func TestBugValidity(t *testing.T) {
 	}
 }
 
-func TestBugSerialisation(t *testing.T) {
+func TestBugCommitLoad(t *testing.T) {
 	bug1 := NewBug()
 
 	bug1.Append(createOp)
@@ -69,22 +69,30 @@ func TestBugSerialisation(t *testing.T) {
 	assert.Nil(t, err)
 
 	bug2, err := ReadLocalBug(repo, bug1.Id())
-	if err != nil {
-		t.Error(err)
-	}
+	assert.NoError(t, err)
+	equivalentBug(t, bug1, bug2)
 
-	// ignore some fields
-	bug2.packs[0].commitHash = bug1.packs[0].commitHash
-	for i := range bug1.packs[0].Operations {
-		bug2.packs[0].Operations[i].base().hash = bug1.packs[0].Operations[i].base().hash
-	}
+	// add more op
+
+	bug1.Append(setTitleOp)
+	bug1.Append(addCommentOp)
+
+	err = bug1.Commit(repo)
+	assert.Nil(t, err)
+
+	bug3, err := ReadLocalBug(repo, bug1.Id())
+	assert.NoError(t, err)
+	equivalentBug(t, bug1, bug3)
+}
+
+func equivalentBug(t *testing.T, expected, actual *Bug) {
+	assert.Equal(t, len(expected.packs), len(actual.packs))
 
-	// check hashes
-	for i := range bug1.packs[0].Operations {
-		if !bug2.packs[0].Operations[i].base().hash.IsValid() {
-			t.Fatal("invalid hash")
+	for i := range expected.packs {
+		for j := range expected.packs[i].Operations {
+			actual.packs[i].Operations[j].base().hash = expected.packs[i].Operations[j].base().hash
 		}
 	}
 
-	assert.Equal(t, bug1, bug2)
+	assert.Equal(t, expected, actual)
 }
  
  
  
    
    @@ -21,17 +21,22 @@ const identityConfigKey = "git-bug.identity"
 var _ Interface = &Identity{}
 
 type Identity struct {
-	id       string
-	Versions []*Version
+	// Id used as unique identifier
+	id string
+
+	lastCommit git.Hash
+
+	// all the successive version of the identity
+	versions []*Version
 }
 
 func NewIdentity(name string, email string) *Identity {
 	return &Identity{
-		Versions: []*Version{
+		versions: []*Version{
 			{
-				Name:  name,
-				Email: email,
-				Nonce: makeNonce(20),
+				name:  name,
+				email: email,
+				nonce: makeNonce(20),
 			},
 		},
 	}
@@ -39,13 +44,13 @@ func NewIdentity(name string, email string) *Identity {
 
 func NewIdentityFull(name string, email string, login string, avatarUrl string) *Identity {
 	return &Identity{
-		Versions: []*Version{
+		versions: []*Version{
 			{
-				Name:      name,
-				Email:     email,
-				Login:     login,
-				AvatarUrl: avatarUrl,
-				Nonce:     makeNonce(20),
+				name:      name,
+				email:     email,
+				login:     login,
+				avatarURL: avatarUrl,
+				nonce:     makeNonce(20),
 			},
 		},
 	}
@@ -84,13 +89,15 @@ func read(repo repository.Repo, ref string) (*Identity, error) {
 
 	hashes, err := repo.ListCommits(ref)
 
-	var versions []*Version
-
 	// TODO: this is not perfect, it might be a command invoke error
 	if err != nil {
 		return nil, ErrIdentityNotExist
 	}
 
+	i := &Identity{
+		id: id,
+	}
+
 	for _, hash := range hashes {
 		entries, err := repo.ListEntries(hash)
 		if err != nil {
@@ -121,14 +128,12 @@ func read(repo repository.Repo, ref string) (*Identity, error) {
 
 		// tag the version with the commit hash
 		version.commitHash = hash
+		i.lastCommit = hash
 
-		versions = append(versions, &version)
+		i.versions = append(i.versions, &version)
 	}
 
-	return &Identity{
-		id:       id,
-		Versions: versions,
-	}, nil
+	return i, nil
 }
 
 // NewFromGitUser will query the repository for user detail and
@@ -182,7 +187,7 @@ func GetUserIdentity(repo repository.Repo) (*Identity, error) {
 }
 
 func (i *Identity) AddVersion(version *Version) {
-	i.Versions = append(i.Versions, version)
+	i.versions = append(i.versions, version)
 }
 
 // Write the identity into the Repository. In particular, this ensure that
@@ -190,11 +195,9 @@ func (i *Identity) AddVersion(version *Version) {
 func (i *Identity) Commit(repo repository.Repo) error {
 	// Todo: check for mismatch between memory and commited data
 
-	var lastCommit git.Hash = ""
-
-	for _, v := range i.Versions {
+	for _, v := range i.versions {
 		if v.commitHash != "" {
-			lastCommit = v.commitHash
+			i.lastCommit = v.commitHash
 			// ignore already commited versions
 			continue
 		}
@@ -215,8 +218,8 @@ func (i *Identity) Commit(repo repository.Repo) error {
 		}
 
 		var commitHash git.Hash
-		if lastCommit != "" {
-			commitHash, err = repo.StoreCommitWithParent(treeHash, lastCommit)
+		if i.lastCommit != "" {
+			commitHash, err = repo.StoreCommitWithParent(treeHash, i.lastCommit)
 		} else {
 			commitHash, err = repo.StoreCommit(treeHash)
 		}
@@ -225,7 +228,8 @@ func (i *Identity) Commit(repo repository.Repo) error {
 			return err
 		}
 
-		lastCommit = commitHash
+		i.lastCommit = commitHash
+		v.commitHash = commitHash
 
 		// if it was the first commit, use the commit hash as the Identity id
 		if i.id == "" {
@@ -238,7 +242,7 @@ func (i *Identity) Commit(repo repository.Repo) error {
 	}
 
 	ref := fmt.Sprintf("%s%s", identityRefPattern, i.id)
-	err := repo.UpdateRef(ref, lastCommit)
+	err := repo.UpdateRef(ref, i.lastCommit)
 
 	if err != nil {
 		return err
@@ -247,31 +251,93 @@ func (i *Identity) Commit(repo repository.Repo) error {
 	return nil
 }
 
+// Merge will merge a different version of the same Identity
+//
+// To make sure that an Identity history can't be altered, a strict fast-forward
+// only policy is applied here. As an Identity should be tied to a single user, this
+// should work in practice but it does leave a possibility that a user would edit his
+// Identity from two different repo concurrently and push the changes in a non-centralized
+// network of repositories. In this case, it would result in some of the repo accepting one
+// version and some other accepting another, preventing the network in general to converge
+// to the same result. This would create a sort of partition of the network, and manual
+// cleaning would be required.
+//
+// An alternative approach would be to have a determinist rebase:
+// - any commits present in both local and remote version would be kept, never changed.
+// - newer commits would be merged in a linear chain of commits, ordered based on the
+//   Lamport time
+//
+// However, this approach leave the possibility, in the case of a compromised crypto keys,
+// of forging a new version with a bogus Lamport time to be inserted before a legit version,
+// invalidating the correct version and hijacking the Identity. There would only be a short
+// period of time where this would be possible (before the network converge) but I'm not
+// confident enough to implement that. I choose the strict fast-forward only approach,
+// despite it's potential problem with two different version as mentioned above.
+func (i *Identity) Merge(repo repository.Repo, other *Identity) (bool, error) {
+	if i.id != other.id {
+		return false, errors.New("merging unrelated identities is not supported")
+	}
+
+	if i.lastCommit == "" || other.lastCommit == "" {
+		return false, errors.New("can't merge identities that has never been stored")
+	}
+
+	/*ancestor, err := repo.FindCommonAncestor(i.lastCommit, other.lastCommit)
+	if err != nil {
+		return false, errors.Wrap(err, "can't find common ancestor")
+	}*/
+
+	modified := false
+	for j, otherVersion := range other.versions {
+		// if there is more version in other, take them
+		if len(i.versions) == j {
+			i.versions = append(i.versions, otherVersion)
+			i.lastCommit = otherVersion.commitHash
+			modified = true
+		}
+
+		// we have a non fast-forward merge.
+		// as explained in the doc above, refusing to merge
+		if i.versions[j].commitHash != otherVersion.commitHash {
+			return false, errors.New("non fast-forward identity merge")
+		}
+	}
+
+	if modified {
+		err := repo.UpdateRef(identityRefPattern+i.id, i.lastCommit)
+		if err != nil {
+			return false, err
+		}
+	}
+
+	return false, nil
+}
+
 // Validate check if the Identity data is valid
 func (i *Identity) Validate() error {
 	lastTime := lamport.Time(0)
 
-	for _, v := range i.Versions {
+	for _, v := range i.versions {
 		if err := v.Validate(); err != nil {
 			return err
 		}
 
-		if v.Time < lastTime {
-			return fmt.Errorf("non-chronological version (%d --> %d)", lastTime, v.Time)
+		if v.time < lastTime {
+			return fmt.Errorf("non-chronological version (%d --> %d)", lastTime, v.time)
 		}
 
-		lastTime = v.Time
+		lastTime = v.time
 	}
 
 	return nil
 }
 
 func (i *Identity) lastVersion() *Version {
-	if len(i.Versions) <= 0 {
+	if len(i.versions) <= 0 {
 		panic("no version at all")
 	}
 
-	return i.Versions[len(i.Versions)-1]
+	return i.versions[len(i.versions)-1]
 }
 
 // Id return the Identity identifier
@@ -286,27 +352,27 @@ func (i *Identity) Id() string {
 
 // Name return the last version of the name
 func (i *Identity) Name() string {
-	return i.lastVersion().Name
+	return i.lastVersion().name
 }
 
 // Email return the last version of the email
 func (i *Identity) Email() string {
-	return i.lastVersion().Email
+	return i.lastVersion().email
 }
 
 // Login return the last version of the login
 func (i *Identity) Login() string {
-	return i.lastVersion().Login
+	return i.lastVersion().login
 }
 
-// Login return the last version of the Avatar URL
+// AvatarUrl return the last version of the Avatar URL
 func (i *Identity) AvatarUrl() string {
-	return i.lastVersion().AvatarUrl
+	return i.lastVersion().avatarURL
 }
 
-// Login return the last version of the valid keys
+// Keys return the last version of the valid keys
 func (i *Identity) Keys() []Key {
-	return i.lastVersion().Keys
+	return i.lastVersion().keys
 }
 
 // IsProtected return true if the chain of git commits started to be signed.
@@ -320,12 +386,12 @@ func (i *Identity) IsProtected() bool {
 func (i *Identity) ValidKeysAtTime(time lamport.Time) []Key {
 	var result []Key
 
-	for _, v := range i.Versions {
-		if v.Time > time {
+	for _, v := range i.versions {
+		if v.time > time {
 			return result
 		}
 
-		result = v.Keys
+		result = v.keys
 	}
 
 	return result
@@ -357,8 +423,8 @@ func (i *Identity) SetMetadata(key string, value string) {
 func (i *Identity) ImmutableMetadata() map[string]string {
 	metadata := make(map[string]string)
 
-	for _, version := range i.Versions {
-		for key, value := range version.Metadata {
+	for _, version := range i.versions {
+		for key, value := range version.metadata {
 			if _, has := metadata[key]; !has {
 				metadata[key] = value
 			}
@@ -373,8 +439,8 @@ func (i *Identity) ImmutableMetadata() map[string]string {
 func (i *Identity) MutableMetadata() map[string]string {
 	metadata := make(map[string]string)
 
-	for _, version := range i.Versions {
-		for key, value := range version.Metadata {
+	for _, version := range i.versions {
+		for key, value := range version.metadata {
 			metadata[key] = value
 		}
 	}
  
  
  
    
    @@ -46,26 +46,6 @@ func Pull(repo repository.ClockedRepo, remote string) error {
 }
 
 // MergeAll will merge all the available remote identity
-// To make sure that an Identity history can't be altered, a strict fast-forward
-// only policy is applied here. As an Identity should be tied to a single user, this
-// should work in practice but it does leave a possibility that a user would edit his
-// Identity from two different repo concurrently and push the changes in a non-centralized
-// network of repositories. In this case, it would result some of the repo accepting one
-// version, some other accepting another, preventing the network in general to converge
-// to the same result. This would create a sort of partition of the network, and manual
-// cleaning would be required.
-//
-// An alternative approach would be to have a determinist rebase:
-// - any commits present in both local and remote version would be kept, never changed.
-// - newer commits would be merged in a linear chain of commits, ordered based on the
-//   Lamport time
-//
-// However, this approach leave the possibility, in the case of a compromised crypto keys,
-// of forging a new version with a bogus Lamport time to be inserted before a legit version,
-// invalidating the correct version and hijacking the Identity. There would only be a short
-// period of time where this would be possible (before the network converge) but I'm not
-// confident enough to implement that. I choose the strict fast-forward only approach,
-// despite it's potential problem with two different version as mentioned above.
 func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
 	out := make(chan MergeResult)
 
@@ -85,20 +65,19 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
 			id := refSplitted[len(refSplitted)-1]
 
 			remoteIdentity, err := ReadLocal(repo, remoteRef)
-			remoteBug, err := readBug(repo, remoteRef)
 
 			if err != nil {
-				out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote bug is not readable").Error())
+				out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote identity is not readable").Error())
 				continue
 			}
 
 			// Check for error in remote data
-			if err := remoteBug.Validate(); err != nil {
-				out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote bug is invalid").Error())
+			if err := remoteIdentity.Validate(); err != nil {
+				out <- newMergeInvalidStatus(id, errors.Wrap(err, "remote identity is invalid").Error())
 				continue
 			}
 
-			localRef := bugsRefPattern + remoteBug.Id()
+			localRef := identityRefPattern + remoteIdentity.Id()
 			localExist, err := repo.RefExist(localRef)
 
 			if err != nil {
@@ -106,7 +85,7 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
 				continue
 			}
 
-			// the bug is not local yet, simply create the reference
+			// the identity is not local yet, simply create the reference
 			if !localExist {
 				err := repo.CopyRef(remoteRef, localRef)
 
@@ -115,18 +94,18 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
 					return
 				}
 
-				out <- newMergeStatus(MergeStatusNew, id, remoteBug)
+				out <- newMergeStatus(MergeStatusNew, id, remoteIdentity)
 				continue
 			}
 
-			localBug, err := readBug(repo, localRef)
+			localIdentity, err := read(repo, localRef)
 
 			if err != nil {
-				out <- newMergeError(errors.Wrap(err, "local bug is not readable"), id)
+				out <- newMergeError(errors.Wrap(err, "local identity is not readable"), id)
 				return
 			}
 
-			updated, err := localBug.Merge(repo, remoteBug)
+			updated, err := localIdentity.Merge(repo, remoteIdentity)
 
 			if err != nil {
 				out <- newMergeInvalidStatus(id, errors.Wrap(err, "merge failed").Error())
@@ -134,9 +113,9 @@ func MergeAll(repo repository.ClockedRepo, remote string) <-chan MergeResult {
 			}
 
 			if updated {
-				out <- newMergeStatus(MergeStatusUpdated, id, localBug)
+				out <- newMergeStatus(MergeStatusUpdated, id, localIdentity)
 			} else {
-				out <- newMergeStatus(MergeStatusNothing, id, localBug)
+				out <- newMergeStatus(MergeStatusNothing, id, localIdentity)
 			}
 		}
 	}()
  
  
  
    
    @@ -6,7 +6,6 @@ import (
 
 	"github.com/MichaelMure/git-bug/repository"
 	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
 )
 
 // Test the commit and load of an Identity with multiple versions
@@ -16,10 +15,10 @@ func TestIdentityCommitLoad(t *testing.T) {
 	// single version
 
 	identity := &Identity{
-		Versions: []*Version{
+		versions: []*Version{
 			{
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
 			},
 		},
 	}
@@ -32,33 +31,33 @@ func TestIdentityCommitLoad(t *testing.T) {
 	loaded, err := ReadLocal(mockRepo, identity.id)
 	assert.Nil(t, err)
 	commitsAreSet(t, loaded)
-	equivalentIdentity(t, identity, loaded)
+	assert.Equal(t, identity, loaded)
 
 	// multiple version
 
 	identity = &Identity{
-		Versions: []*Version{
+		versions: []*Version{
 			{
-				Time:  100,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  100,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyA"},
 				},
 			},
 			{
-				Time:  200,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  200,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyB"},
 				},
 			},
 			{
-				Time:  201,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  201,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyC"},
 				},
 			},
@@ -73,24 +72,24 @@ func TestIdentityCommitLoad(t *testing.T) {
 	loaded, err = ReadLocal(mockRepo, identity.id)
 	assert.Nil(t, err)
 	commitsAreSet(t, loaded)
-	equivalentIdentity(t, identity, loaded)
+	assert.Equal(t, identity, loaded)
 
 	// add more version
 
 	identity.AddVersion(&Version{
-		Time:  201,
-		Name:  "René Descartes",
-		Email: "rene.descartes@example.com",
-		Keys: []Key{
+		time:  201,
+		name:  "René Descartes",
+		email: "rene.descartes@example.com",
+		keys: []Key{
 			{PubKey: "pubkeyD"},
 		},
 	})
 
 	identity.AddVersion(&Version{
-		Time:  300,
-		Name:  "René Descartes",
-		Email: "rene.descartes@example.com",
-		Keys: []Key{
+		time:  300,
+		name:  "René Descartes",
+		email: "rene.descartes@example.com",
+		keys: []Key{
 			{PubKey: "pubkeyE"},
 		},
 	})
@@ -103,66 +102,56 @@ func TestIdentityCommitLoad(t *testing.T) {
 	loaded, err = ReadLocal(mockRepo, identity.id)
 	assert.Nil(t, err)
 	commitsAreSet(t, loaded)
-	equivalentIdentity(t, identity, loaded)
+	assert.Equal(t, identity, loaded)
 }
 
 func commitsAreSet(t *testing.T, identity *Identity) {
-	for _, version := range identity.Versions {
+	for _, version := range identity.versions {
 		assert.NotEmpty(t, version.commitHash)
 	}
 }
 
-func equivalentIdentity(t *testing.T, expected, actual *Identity) {
-	require.Equal(t, len(expected.Versions), len(actual.Versions))
-
-	for i, version := range expected.Versions {
-		actual.Versions[i].commitHash = version.commitHash
-	}
-
-	assert.Equal(t, expected, actual)
-}
-
 // Test that the correct crypto keys are returned for a given lamport time
 func TestIdentity_ValidKeysAtTime(t *testing.T) {
 	identity := Identity{
-		Versions: []*Version{
+		versions: []*Version{
 			{
-				Time:  100,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  100,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyA"},
 				},
 			},
 			{
-				Time:  200,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  200,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyB"},
 				},
 			},
 			{
-				Time:  201,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  201,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyC"},
 				},
 			},
 			{
-				Time:  201,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  201,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyD"},
 				},
 			},
 			{
-				Time:  300,
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
-				Keys: []Key{
+				time:  300,
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
+				keys: []Key{
 					{PubKey: "pubkeyE"},
 				},
 			},
@@ -197,8 +186,8 @@ func TestMetadata(t *testing.T) {
 
 	// try override
 	identity.AddVersion(&Version{
-		Name:  "René Descartes",
-		Email: "rene.descartes@example.com",
+		name:  "René Descartes",
+		email: "rene.descartes@example.com",
 	})
 
 	identity.SetMetadata("key1", "value2")
@@ -226,10 +215,10 @@ func TestJSON(t *testing.T) {
 	mockRepo := repository.NewMockRepoForTest()
 
 	identity := &Identity{
-		Versions: []*Version{
+		versions: []*Version{
 			{
-				Name:  "René Descartes",
-				Email: "rene.descartes@example.com",
+				name:  "René Descartes",
+				email: "rene.descartes@example.com",
 			},
 		},
 	}
  
  
  
    
    @@ -24,25 +24,25 @@ type Version struct {
 
 	// The lamport time at which this version become effective
 	// The reference time is the bug edition lamport clock
-	Time lamport.Time
+	time lamport.Time
 
-	Name      string
-	Email     string
-	Login     string
-	AvatarUrl string
+	name      string
+	email     string
+	login     string
+	avatarURL string
 
 	// The set of keys valid at that time, from this version onward, until they get removed
 	// in a new version. This allow to have multiple key for the same identity (e.g. one per
 	// device) as well as revoke key.
-	Keys []Key
+	keys []Key
 
 	// This optional array is here to ensure a better randomness of the identity id to avoid collisions.
 	// It has no functional purpose and should be ignored.
 	// It is advised to fill this array if there is not enough entropy, e.g. if there is no keys.
-	Nonce []byte
+	nonce []byte
 
 	// A set of arbitrary key/value to store metadata about a version or about an Identity in general.
-	Metadata map[string]string
+	metadata map[string]string
 }
 
 type VersionJSON struct {
@@ -62,14 +62,14 @@ type VersionJSON struct {
 func (v *Version) MarshalJSON() ([]byte, error) {
 	return json.Marshal(VersionJSON{
 		FormatVersion: formatVersion,
-		Time:          v.Time,
-		Name:          v.Name,
-		Email:         v.Email,
-		Login:         v.Login,
-		AvatarUrl:     v.AvatarUrl,
-		Keys:          v.Keys,
-		Nonce:         v.Nonce,
-		Metadata:      v.Metadata,
+		Time:          v.time,
+		Name:          v.name,
+		Email:         v.email,
+		Login:         v.login,
+		AvatarUrl:     v.avatarURL,
+		Keys:          v.keys,
+		Nonce:         v.nonce,
+		Metadata:      v.metadata,
 	})
 }
 
@@ -84,56 +84,56 @@ func (v *Version) UnmarshalJSON(data []byte) error {
 		return fmt.Errorf("unknown format version %v", aux.FormatVersion)
 	}
 
-	v.Time = aux.Time
-	v.Name = aux.Name
-	v.Email = aux.Email
-	v.Login = aux.Login
-	v.AvatarUrl = aux.AvatarUrl
-	v.Keys = aux.Keys
-	v.Nonce = aux.Nonce
-	v.Metadata = aux.Metadata
+	v.time = aux.Time
+	v.name = aux.Name
+	v.email = aux.Email
+	v.login = aux.Login
+	v.avatarURL = aux.AvatarUrl
+	v.keys = aux.Keys
+	v.nonce = aux.Nonce
+	v.metadata = aux.Metadata
 
 	return nil
 }
 
 func (v *Version) Validate() error {
-	if text.Empty(v.Name) && text.Empty(v.Login) {
+	if text.Empty(v.name) && text.Empty(v.login) {
 		return fmt.Errorf("either name or login should be set")
 	}
 
-	if strings.Contains(v.Name, "\n") {
+	if strings.Contains(v.name, "\n") {
 		return fmt.Errorf("name should be a single line")
 	}
 
-	if !text.Safe(v.Name) {
+	if !text.Safe(v.name) {
 		return fmt.Errorf("name is not fully printable")
 	}
 
-	if strings.Contains(v.Login, "\n") {
+	if strings.Contains(v.login, "\n") {
 		return fmt.Errorf("login should be a single line")
 	}
 
-	if !text.Safe(v.Login) {
+	if !text.Safe(v.login) {
 		return fmt.Errorf("login is not fully printable")
 	}
 
-	if strings.Contains(v.Email, "\n") {
+	if strings.Contains(v.email, "\n") {
 		return fmt.Errorf("email should be a single line")
 	}
 
-	if !text.Safe(v.Email) {
+	if !text.Safe(v.email) {
 		return fmt.Errorf("email is not fully printable")
 	}
 
-	if v.AvatarUrl != "" && !text.ValidUrl(v.AvatarUrl) {
+	if v.avatarURL != "" && !text.ValidUrl(v.avatarURL) {
 		return fmt.Errorf("avatarUrl is not a valid URL")
 	}
 
-	if len(v.Nonce) > 64 {
+	if len(v.nonce) > 64 {
 		return fmt.Errorf("nonce is too big")
 	}
 
-	for _, k := range v.Keys {
+	for _, k := range v.keys {
 		if err := k.Validate(); err != nil {
 			return errors.Wrap(err, "invalid key")
 		}
@@ -178,20 +178,20 @@ func makeNonce(len int) []byte {
 // SetMetadata store arbitrary metadata about a version or an Identity in general
 // If the Version has been commit to git already, it won't be overwritten.
 func (v *Version) SetMetadata(key string, value string) {
-	if v.Metadata == nil {
-		v.Metadata = make(map[string]string)
+	if v.metadata == nil {
+		v.metadata = make(map[string]string)
 	}
 
-	v.Metadata[key] = value
+	v.metadata[key] = value
 }
 
 // GetMetadata retrieve arbitrary metadata about the Version
 func (v *Version) GetMetadata(key string) (string, bool) {
-	val, ok := v.Metadata[key]
+	val, ok := v.metadata[key]
 	return val, ok
 }
 
 // AllMetadata return all metadata for this Identity
 func (v *Version) AllMetadata() map[string]string {
-	return v.Metadata
+	return v.metadata
 }