diff --git a/conf/core/cache.ccf b/conf/core/cache.ccf
index 821e5d7862efb21e0aa13f8410886c6c14b10a7c..b4e1f93596a6170ef04ec373dc7a8d70e51fedcc 100644
--- a/conf/core/cache.ccf
+++ b/conf/core/cache.ccf
@@ -28,6 +28,8 @@ jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=103
 jcs.region.BACKEND_SparseEntities
 jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1002
 
+jcs.region.BACKEND_RetrieveFullVersionInfo
+jcs.region.BACKEND_RetrieveFullVersionInfo.cacheattributes.MaxObjects=1006
 
 # PAM UserSource Caching: Cached Items expire after 60 seconds if they are not requested (idle) and after 600 seconds max.
 # PAM_UnixUserGroups
diff --git a/src/main/java/caosdb/server/database/BackendTransaction.java b/src/main/java/caosdb/server/database/BackendTransaction.java
index 14e65e86bd9fe05b074c731e27b601fa4ed51f68..a8f27a135094b2cab08a73bfd2e4b3f32e791399 100644
--- a/src/main/java/caosdb/server/database/BackendTransaction.java
+++ b/src/main/java/caosdb/server/database/BackendTransaction.java
@@ -48,6 +48,7 @@ import caosdb.server.database.backend.implementation.MySQL.MySQLRegisterSubDomai
 import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAll;
 import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAllUncheckedFiles;
 import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveDatatypes;
+import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveFullVersion;
 import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveLogRecord;
 import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveParents;
 import caosdb.server.database.backend.implementation.MySQL.MySQLRetrievePasswordValidator;
@@ -103,6 +104,7 @@ import caosdb.server.database.backend.interfaces.RegisterSubDomainImpl;
 import caosdb.server.database.backend.interfaces.RetrieveAllImpl;
 import caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesImpl;
 import caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl;
+import caosdb.server.database.backend.interfaces.RetrieveFullVersionInfoImpl;
 import caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl;
 import caosdb.server.database.backend.interfaces.RetrieveParentsImpl;
 import caosdb.server.database.backend.interfaces.RetrievePasswordValidatorImpl;
@@ -204,6 +206,7 @@ public abstract class BackendTransaction implements Undoable {
       setImpl(
           RetrieveQueryTemplateDefinitionImpl.class, MySQLRetrieveQueryTemplateDefinition.class);
       setImpl(InsertEntityDatatypeImpl.class, MySQLInsertEntityDatatype.class);
+      setImpl(RetrieveFullVersionInfoImpl.class, MySQLRetrieveFullVersion.class);
     }
   }
 
diff --git a/src/main/java/caosdb/server/database/CacheableBackendTransaction.java b/src/main/java/caosdb/server/database/CacheableBackendTransaction.java
index fc4c9659d9a8ea80393bebad945bd6badf9580c4..0883c291c43c29093f8a5b93d41631ee21284ea8 100644
--- a/src/main/java/caosdb/server/database/CacheableBackendTransaction.java
+++ b/src/main/java/caosdb/server/database/CacheableBackendTransaction.java
@@ -51,7 +51,7 @@ public abstract class CacheableBackendTransaction<K, V extends Serializable>
   private final V execute(final K key) throws TransactionException {
     // get from cache if possible...
     if (cacheIsEnabled() && key != null) {
-      final V cached = getCache().get(getKey());
+      final V cached = getCache().get(key);
       if (cached != null) {
         this.cached = true;
         return cached;
@@ -64,7 +64,7 @@ public abstract class CacheableBackendTransaction<K, V extends Serializable>
     if (notCached != null) {
       if (cacheIsEnabled() && key != null) {
         // now cache if possible
-        getCache().put(getKey(), notCached);
+        getCache().put(key, notCached);
       }
     }
     return notCached;
diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveFullVersion.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveFullVersion.java
new file mode 100644
index 0000000000000000000000000000000000000000..db28b8c21720bda2a1621eb7a7a121ba81dbcb1c
--- /dev/null
+++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveFullVersion.java
@@ -0,0 +1,58 @@
+package caosdb.server.database.backend.implementation.MySQL;
+
+import caosdb.server.database.DatabaseUtils;
+import caosdb.server.database.access.Access;
+import caosdb.server.database.backend.interfaces.RetrieveFullVersionInfoImpl;
+import caosdb.server.database.exceptions.TransactionException;
+import caosdb.server.database.proto.VersionHistoryItem;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+public class MySQLRetrieveFullVersion extends MySQLTransaction
+    implements RetrieveFullVersionInfoImpl {
+
+  public static final String VERSION_HISTORY_STMT = "CALL get_version_history(?)";
+
+  public MySQLRetrieveFullVersion(Access access) {
+    super(access);
+  }
+
+  @Override
+  public HashMap<String, VersionHistoryItem> execute(Integer entityId) {
+
+    HashMap<String, VersionHistoryItem> result = new HashMap<>();
+    try {
+      PreparedStatement s = prepareStatement(VERSION_HISTORY_STMT);
+      s.setInt(1, entityId);
+      ResultSet rs = s.executeQuery();
+
+      while (rs.next()) {
+        String childId = DatabaseUtils.bytes2UTF8(rs.getBytes("child"));
+        String parentId = DatabaseUtils.bytes2UTF8(rs.getBytes("parent"));
+        Long childSeconds = rs.getLong("child_seconds");
+        Integer childNanos = rs.getInt("child_nanos");
+        VersionHistoryItem v = result.get(childId);
+        if (v == null) {
+          v = new VersionHistoryItem();
+          v.id = childId;
+          v.seconds = childSeconds;
+          v.nanos = childNanos;
+          result.put(childId, v);
+        }
+
+        if (parentId != null) {
+          if (v.parents == null) {
+            v.parents = new LinkedList<>();
+          }
+          v.parents.add(parentId);
+        }
+      }
+    } catch (SQLException | ConnectionException e) {
+      throw new TransactionException(e);
+    }
+    return result;
+  }
+}
diff --git a/src/main/java/caosdb/server/database/backend/interfaces/RetrieveFullVersionInfoImpl.java b/src/main/java/caosdb/server/database/backend/interfaces/RetrieveFullVersionInfoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6201cec61c889d79f53dd23595e0d4a501bc8de
--- /dev/null
+++ b/src/main/java/caosdb/server/database/backend/interfaces/RetrieveFullVersionInfoImpl.java
@@ -0,0 +1,9 @@
+package caosdb.server.database.backend.interfaces;
+
+import caosdb.server.database.proto.VersionHistoryItem;
+import java.util.HashMap;
+
+public interface RetrieveFullVersionInfoImpl extends BackendTransactionImpl {
+
+  public HashMap<String, VersionHistoryItem> execute(Integer entityId);
+}
diff --git a/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
index c732d25c8384fca1768995858223a2b3e2385c80..a2e4de6482d78053ab01c70ea3634c3f8af232a3 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
@@ -42,7 +42,7 @@ public class DeleteSparseEntity extends BackendTransaction {
 
   @Override
   protected void execute() {
-    RetrieveSparseEntity.removeCached(this.entity.getIdVersion());
+    RetrieveSparseEntity.removeCached(this.entity);
     if (entity.hasFileProperties()) {
       GetFileRecordByPath.removeCached(this.entity.getFileProperties().getPath());
     }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java
index c59f912a8c7991febbe7bfcad7ae42e23efffe0a..c8e20895711e16c40c75c89c9776e8ad55851117 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java
@@ -30,6 +30,7 @@ import caosdb.server.database.exceptions.IntegrityException;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.entity.EntityInterface;
+import caosdb.server.entity.Version;
 import caosdb.server.utils.Undoable;
 
 public class InsertSparseEntity extends BackendTransaction {
@@ -68,6 +69,6 @@ public class InsertSparseEntity extends BackendTransaction {
               public void cleanUp() {}
             });
     this.entity.setId(e.id);
-    this.entity.setVersion(e.version);
+    this.entity.setVersion(new Version(e.version));
   }
 }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java
index 7ac8c1592e0cb275e60008532cdabb33919369a9..8e9c0ca3034d60d710e6e1e8a051b8e36024e625 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java
@@ -60,6 +60,8 @@ public class RetrieveFullEntity extends BackendTransaction {
           execute(new RetrieveParents(e));
 
           execute(new RetrieveProperties(e));
+
+          execute(new RetrieveVersionInfo(e));
         }
       }
     }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullVersionHistory.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullVersionHistory.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c61811e5fcaf5e3c9986b11cae486d71a8da8aa
--- /dev/null
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullVersionHistory.java
@@ -0,0 +1,56 @@
+package caosdb.server.database.backend.transaction;
+
+import caosdb.server.database.CacheableBackendTransaction;
+import caosdb.server.database.backend.interfaces.RetrieveFullVersionInfoImpl;
+import caosdb.server.database.exceptions.TransactionException;
+import caosdb.server.database.proto.VersionHistoryItem;
+import caosdb.server.entity.EntityInterface;
+import java.util.Collection;
+import java.util.HashMap;
+
+public abstract class RetrieveFullVersionHistory
+    extends CacheableBackendTransaction<Integer, HashMap<String, VersionHistoryItem>> {
+
+  // TODO
+  // private static final ICacheAccess<String, Version> cache =
+  // Cache.getCache("BACKEND_RetrieveFullVersionInfo");
+  private EntityInterface entity;
+  private HashMap<String, VersionHistoryItem> map;
+
+  public static void removeCached(Integer entityId) {
+    // TODO
+  }
+
+  public RetrieveFullVersionHistory(EntityInterface e) {
+    super(null); // TODO
+    this.entity = e;
+  }
+
+  @Override
+  public HashMap<String, VersionHistoryItem> executeNoCache() throws TransactionException {
+    RetrieveFullVersionInfoImpl impl = getImplementation(RetrieveFullVersionInfoImpl.class);
+    return impl.execute(getKey());
+  }
+
+  @Override
+  protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException {
+    this.map = map;
+  }
+
+  @Override
+  protected Integer getKey() {
+    return entity.getId();
+  }
+
+  public HashMap<String, VersionHistoryItem> getMap() {
+    return this.map;
+  }
+
+  public EntityInterface getEntity() {
+    return this.entity;
+  }
+
+  public Collection<VersionHistoryItem> getList() {
+    return this.map.values();
+  }
+}
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java
index fbb257f780b0594d7859a0fc2deefc8183be30fe..9fffcae8ade2d917562edffe5675a55f50d576d0 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java
@@ -61,7 +61,7 @@ public class RetrieveParents
   @Override
   public ArrayList<VerySparseEntity> executeNoCache() throws TransactionException {
     final RetrieveParentsImpl t = getImplementation(RetrieveParentsImpl.class);
-    return t.execute(this.entity.getId(), this.entity.getVersion());
+    return t.execute(this.entity.getId(), this.entity.getVersion().getId());
   }
 
   @Override
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
index c0bcb8e8563fe276f19a668e8d1248c0dc287d23..822f57fd49e54d7517578592acf09100924fe81b 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
@@ -63,7 +63,7 @@ public class RetrieveProperties
   @Override
   public ArrayList<ProtoProperty> executeNoCache() throws TransactionException {
     final RetrievePropertiesImpl t = getImplementation(RetrievePropertiesImpl.class);
-    return t.execute(this.entity.getId(), this.entity.getVersion());
+    return t.execute(this.entity.getId(), this.entity.getVersion().getId());
   }
 
   @Override
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java
index b3dfb14695b7a2449460d4c024448f0e30e1bad3..0c96c72cb0be41aaf368c22009526914994bc8ec 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java
@@ -40,6 +40,6 @@ public class RetrieveQueryTemplateDefinition extends BackendTransaction {
     final RetrieveQueryTemplateDefinitionImpl t =
         getImplementation(RetrieveQueryTemplateDefinitionImpl.class);
     this.entity.setQueryTemplateDefinition(
-        t.retrieve(this.entity.getId(), this.entity.getVersion()));
+        t.retrieve(this.entity.getId(), this.entity.getVersion().getId()));
   }
 }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java
index db6b38bd197d8069e5d33804a7aaf801d0c9929b..6ad58df839e2f03101e2265c32f894992809dcee 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java
@@ -42,13 +42,14 @@ public class RetrieveSparseEntity extends CacheableBackendTransaction<String, Sp
       Cache.getCache("BACKEND_SparseEntities");
 
   /**
-   * To be called by {@link UpdateSparseEntity} and {@link DeleteEntity} on execution.
+   * To be called by {@link UpdateSparseEntity} and {@link DeleteSparseEntity} on execution.
    *
-   * @param idVersion
+   * @param entity
    */
-  public static void removeCached(final String idVersion) {
-    if (idVersion != null && cache != null) {
-      cache.remove(idVersion);
+  public static void removeCached(final EntityInterface entity) {
+    if (entity != null && cache != null) {
+      cache.remove(entity.getId().toString());
+      cache.remove(entity.getIdVersion());
     }
   }
 
@@ -64,7 +65,7 @@ public class RetrieveSparseEntity extends CacheableBackendTransaction<String, Sp
   @Override
   public SparseEntity executeNoCache() throws TransactionException {
     final RetrieveSparseEntityImpl t = getImplementation(RetrieveSparseEntityImpl.class);
-    final SparseEntity ret = t.execute(getEntity().getId(), getEntity().getVersion());
+    final SparseEntity ret = t.execute(getEntity().getId(), getEntity().getVersion().getId());
     if (ret == null) {
       this.entity.setEntityStatus(EntityStatus.NONEXISTENT);
     }
@@ -79,6 +80,12 @@ public class RetrieveSparseEntity extends CacheableBackendTransaction<String, Sp
 
   @Override
   protected String getKey() {
+    if ("HEAD".equalsIgnoreCase(entity.getVersion().getId())) {
+      return this.entity.getId().toString();
+    } else if (entity.hasVersion()
+        && entity.getVersion().getId().toUpperCase().startsWith("HEAD")) {
+      return null;
+    }
     return this.entity.getIdVersion();
   }
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveVersionInfo.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveVersionInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..139e797968efbe3506a6945ef4ccc485b5a102ca
--- /dev/null
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveVersionInfo.java
@@ -0,0 +1,60 @@
+package caosdb.server.database.backend.transaction;
+
+import caosdb.datetime.UTCDateTime;
+import caosdb.server.database.exceptions.TransactionException;
+import caosdb.server.database.proto.VersionHistoryItem;
+import caosdb.server.entity.EntityInterface;
+import caosdb.server.entity.Version;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+public class RetrieveVersionInfo extends RetrieveFullVersionHistory {
+
+  public RetrieveVersionInfo(EntityInterface e) {
+    super(e);
+  }
+
+  @Override
+  protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException {
+    super.process(map);
+    if (!map.isEmpty()) getVersion();
+  }
+
+  public Version getVersion() {
+    Version v = getEntity().getVersion();
+    VersionHistoryItem i = getMap().get(v.getId());
+    if (i != null) v.setDate(UTCDateTime.UTCSeconds(i.seconds, i.nanos));
+
+    v.setPredecessors(getPredecessors(v.getId()));
+    v.setSuccessors(getSuccessors(v.getId()));
+    return v;
+  }
+
+  private LinkedList<Version> getSuccessors(String id) {
+    LinkedList<Version> result = new LinkedList<>();
+
+    outer:
+    for (VersionHistoryItem i : getList()) {
+      if (i.parents != null)
+        for (String p : i.parents) {
+          if (id.equals(p)) {
+            Version successor = new Version(i.id, i.seconds, i.nanos);
+            result.add(successor);
+            continue outer;
+          }
+        }
+    }
+    return result;
+  }
+
+  private LinkedList<Version> getPredecessors(String id) {
+    LinkedList<Version> result = new LinkedList<>();
+    if (getMap().containsKey(id) && getMap().get(id).parents != null)
+      for (String p : getMap().get(id).parents) {
+        VersionHistoryItem i = getMap().get(p);
+        Version predecessor = new Version(i.id, i.seconds, i.nanos);
+        result.add(predecessor);
+      }
+    return result;
+  }
+}
diff --git a/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java b/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java
index 6378e8bbbbd8aee87382d226df0691d004e641aa..a7c9ba43f32b1ef97a6a09544041b39a2cd5c71a 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java
@@ -53,6 +53,8 @@ public class UpdateEntity extends BackendTransaction {
         execute(new InsertEntityValue(e));
 
         execute(new InsertEntityProperties(e));
+
+        execute(new RetrieveVersionInfo(e));
       }
     }
   }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java
index c3149a765163e0ac577dd6e0a2415330cce5b58d..309ff9cbde0131f4b90cc89301a2338a8b92971f 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java
@@ -29,6 +29,7 @@ import caosdb.server.database.backend.interfaces.UpdateSparseEntityImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.entity.EntityInterface;
+import caosdb.server.entity.Version;
 
 public class UpdateSparseEntity extends BackendTransaction {
 
@@ -40,7 +41,7 @@ public class UpdateSparseEntity extends BackendTransaction {
 
   @Override
   public void execute() throws TransactionException {
-    RetrieveSparseEntity.removeCached(this.entity.getIdVersion());
+    RetrieveSparseEntity.removeCached(this.entity);
     if (entity.hasFileProperties()) {
       GetFileRecordByPath.removeCached(this.entity.getFileProperties().getPath());
     }
@@ -51,6 +52,6 @@ public class UpdateSparseEntity extends BackendTransaction {
 
     t.execute(spe);
 
-    this.entity.setVersion(spe.version);
+    this.entity.setVersion(new Version(spe.version));
   }
 }
diff --git a/src/main/java/caosdb/server/database/proto/VersionHistoryItem.java b/src/main/java/caosdb/server/database/proto/VersionHistoryItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..e671950f39f40c0b93069d031f636ad964560508
--- /dev/null
+++ b/src/main/java/caosdb/server/database/proto/VersionHistoryItem.java
@@ -0,0 +1,13 @@
+package caosdb.server.database.proto;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+
+public class VersionHistoryItem implements Serializable {
+
+  private static final long serialVersionUID = 7855704308135158698L;
+  public String id = null;
+  public LinkedList<String> parents = null;
+  public Long seconds = null;
+  public Integer nanos = null;
+}
diff --git a/src/main/java/caosdb/server/entity/DeleteEntity.java b/src/main/java/caosdb/server/entity/DeleteEntity.java
index f31fbb47a9e25f2d00dfa5f2874925bd504f23fe..83b7fdcf35c60358b007d1af42930bcc5c310e75 100644
--- a/src/main/java/caosdb/server/entity/DeleteEntity.java
+++ b/src/main/java/caosdb/server/entity/DeleteEntity.java
@@ -30,6 +30,6 @@ public class DeleteEntity extends Entity {
 
   public DeleteEntity(int id, String version) {
     super(id);
-    setVersion(version);
+    setVersion(new Version(version));
   }
 }
diff --git a/src/main/java/caosdb/server/entity/Entity.java b/src/main/java/caosdb/server/entity/Entity.java
index c1579fb005b4a166b9347e434b8b740b221e1d56..9bd0b6ddfed6fbc42896bb19b8a15f411414a884 100644
--- a/src/main/java/caosdb/server/entity/Entity.java
+++ b/src/main/java/caosdb/server/entity/Entity.java
@@ -795,7 +795,9 @@ public class Entity extends AbstractObservable implements EntityInterface {
     final CollectionValue vals = new CollectionValue();
     int pidx = 0;
     for (final Element pe : element.getChildren()) {
-      if (pe.getName().equalsIgnoreCase("EmptyString")) {
+      if (pe.getName().equalsIgnoreCase("Version")) {
+        // TODO
+      } else if (pe.getName().equalsIgnoreCase("EmptyString")) {
         // special case: empty string which cannot be distinguished from null
         // values otherwise.
         setValue(new GenericValue(""));
@@ -1021,8 +1023,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   private boolean datatypeOverride = false;
-  private String version = null;
-  private UTCDateTime versionDate = null;
+  private Version version = new Version();
 
   @Override
   public EntityInterface setDatatypeOverride(final boolean b) {
@@ -1067,10 +1068,11 @@ public class Entity extends AbstractObservable implements EntityInterface {
     setId(spe.id);
     this.setRole(spe.role);
     setEntityACL(spe.acl);
-    this.version = spe.version;
+    UTCDateTime versionDate = null;
     if (spe.versionSeconds != null) {
-      this.versionDate = UTCDateTime.UTCSeconds(spe.versionSeconds, spe.versionNanos);
+      versionDate = UTCDateTime.UTCSeconds(spe.versionSeconds, spe.versionNanos);
     }
+    this.version = new Version(spe.version, versionDate);
 
     if (!isNameOverride()) {
       setName(spe.name);
@@ -1121,46 +1123,26 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   @Override
-  public UTCDateTime getVersionDate() {
-    return this.versionDate;
-  }
-
-  @Override
-  public String getVersion() {
+  public Version getVersion() {
     return this.version;
   }
 
   @Override
   public boolean hasVersion() {
-    return this.version != null;
-  }
-
-  @Override
-  public boolean hasVersionDate() {
-    return this.versionDate != null;
+    return this.version.getId() != null;
   }
 
   @Override
-  public void setVersion(String version) {
+  public void setVersion(Version version) {
     this.version = version;
   }
 
-  @Override
-  public void setVersionDate(Long versionSeconds, Integer versionNanos) {
-    this.versionDate = UTCDateTime.UTCSeconds(versionSeconds, versionNanos);
-  }
-
-  @Override
-  public void setVersionDate(UTCDateTime versionDate) {
-    this.versionDate = versionDate;
-  }
-
   @Override
   public String getIdVersion() {
     if (!this.hasId()) {
       return null;
     } else if (this.hasVersion()) {
-      return new StringBuilder().append(getId()).append(getVersion()).toString();
+      return new StringBuilder().append(getId()).append(getVersion().getId()).toString();
     }
     return getId().toString();
   }
diff --git a/src/main/java/caosdb/server/entity/EntityInterface.java b/src/main/java/caosdb/server/entity/EntityInterface.java
index a39a43d65c478c082bb215c0b8565c4890b81b6e..657727055b4289046a4ee893af0fa424a750a261 100644
--- a/src/main/java/caosdb/server/entity/EntityInterface.java
+++ b/src/main/java/caosdb/server/entity/EntityInterface.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.entity;
 
-import caosdb.datetime.UTCDateTime;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.database.proto.VerySparseEntity;
 import caosdb.server.datatype.AbstractDatatype;
@@ -186,17 +185,9 @@ public interface EntityInterface
 
   public abstract void setQueryTemplateDefinition(String query);
 
-  public abstract UTCDateTime getVersionDate();
-
-  public abstract String getVersion();
+  public abstract Version getVersion();
 
   public abstract boolean hasVersion();
 
-  public abstract boolean hasVersionDate();
-
-  public abstract void setVersionDate(Long versionSeconds, Integer versionNanos);
-
-  public abstract void setVersion(String version);
-
-  public abstract void setVersionDate(UTCDateTime versionDate);
+  public abstract void setVersion(Version version);
 }
diff --git a/src/main/java/caosdb/server/entity/RetrieveEntity.java b/src/main/java/caosdb/server/entity/RetrieveEntity.java
index 64b99a2f66983355802b4db20300874e548e6924..57d7ae48193ff81d7be2f4dfba97166d8cd05ff7 100644
--- a/src/main/java/caosdb/server/entity/RetrieveEntity.java
+++ b/src/main/java/caosdb/server/entity/RetrieveEntity.java
@@ -34,11 +34,11 @@ public class RetrieveEntity extends Entity {
 
   public RetrieveEntity(int id, String version) {
     super(id);
-    this.setVersion(version);
+    this.setVersion(new Version(version));
   }
 
   public RetrieveEntity(String name, String version) {
     super(name);
-    this.setVersion(version);
+    this.setVersion(new Version(version));
   }
 }
diff --git a/src/main/java/caosdb/server/entity/Version.java b/src/main/java/caosdb/server/entity/Version.java
new file mode 100644
index 0000000000000000000000000000000000000000..43cdcd54ecb1dde9143f18033b9eb42575a67a0f
--- /dev/null
+++ b/src/main/java/caosdb/server/entity/Version.java
@@ -0,0 +1,59 @@
+package caosdb.server.entity;
+
+import caosdb.datetime.UTCDateTime;
+import java.util.LinkedList;
+
+public class Version {
+
+  private String id = null;
+  private LinkedList<Version> predecessors = null;
+  private LinkedList<Version> successors = null;
+  private UTCDateTime date = null;
+
+  public Version(String id, long seconds, int nanos) {
+    this(id, UTCDateTime.UTCSeconds(seconds, nanos));
+  }
+
+  public Version(String id, UTCDateTime date) {
+    this.id = id;
+    this.date = date;
+  }
+
+  public Version(String id) {
+    this(id, null);
+  }
+
+  public Version() {}
+
+  public UTCDateTime getDate() {
+    return date;
+  }
+
+  public void setDate(UTCDateTime date) {
+    this.date = date;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public LinkedList<Version> getSuccessors() {
+    return successors;
+  }
+
+  public void setSuccessors(LinkedList<Version> successors) {
+    this.successors = successors;
+  }
+
+  public LinkedList<Version> getPredecessors() {
+    return predecessors;
+  }
+
+  public void setPredecessors(LinkedList<Version> predecessors) {
+    this.predecessors = predecessors;
+  }
+}
diff --git a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java
index 85719dc62041a63930ab0ca711f870397fd2ce5d..71e1ad21a67f29bedbfd59fcd5bf645237023670 100644
--- a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java
+++ b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.entity.wrapper;
 
-import caosdb.datetime.UTCDateTime;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.database.proto.VerySparseEntity;
 import caosdb.server.datatype.AbstractDatatype;
@@ -32,6 +31,7 @@ import caosdb.server.entity.FileProperties;
 import caosdb.server.entity.Message;
 import caosdb.server.entity.Role;
 import caosdb.server.entity.StatementStatus;
+import caosdb.server.entity.Version;
 import caosdb.server.entity.container.ParentContainer;
 import caosdb.server.entity.container.PropertyContainer;
 import caosdb.server.entity.xml.ToElementStrategy;
@@ -554,12 +554,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public UTCDateTime getVersionDate() {
-    return this.entity.getVersionDate();
-  }
-
-  @Override
-  public String getVersion() {
+  public Version getVersion() {
     return this.entity.getVersion();
   }
 
@@ -569,25 +564,10 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public boolean hasVersionDate() {
-    return this.entity.hasVersionDate();
-  }
-
-  @Override
-  public void setVersion(String version) {
+  public void setVersion(Version version) {
     this.entity.setVersion(version);
   }
 
-  @Override
-  public void setVersionDate(Long versionSeconds, Integer versionNanos) {
-    this.entity.setVersionDate(versionSeconds, versionNanos);
-  }
-
-  @Override
-  public void setVersionDate(UTCDateTime versionDate) {
-    this.entity.setVersionDate(versionDate);
-  }
-
   @Override
   public String getIdVersion() {
     return this.entity.getIdVersion();
diff --git a/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java b/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java
index 0697c076d91b5bb9519341020f9b2698326ef6cd..bfa5e8854765f1271981f5a28b60c1aa3450b8f8 100644
--- a/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java
+++ b/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java
@@ -27,7 +27,6 @@ import caosdb.server.entity.Message;
 import caosdb.server.utils.EntityStatus;
 import caosdb.server.utils.TransactionLogMessage;
 import java.util.Comparator;
-import java.util.TimeZone;
 import org.apache.shiro.SecurityUtils;
 import org.jdom2.Content;
 import org.jdom2.Content.CType;
@@ -52,11 +51,8 @@ public class EntityToElementStrategy implements ToElementStrategy {
       element.setAttribute("id", Integer.toString(entity.getId()));
     }
     if (setFieldStrategy.isToBeSet("version") && entity.hasVersion()) {
-      element.setAttribute("version", entity.getVersion());
-    }
-    if (setFieldStrategy.isToBeSet("versionDate") && entity.hasVersionDate()) {
-      element.setAttribute(
-          "versionDate", entity.getVersionDate().toDateTimeString(TimeZone.getDefault()));
+      Element v = new VersionXMLConverter().toElement(entity.getVersion());
+      element.addContent(v);
     }
     if (setFieldStrategy.isToBeSet("cuid") && entity.hasCuid()) {
       element.setAttribute("cuid", entity.getCuid());
diff --git a/src/main/java/caosdb/server/entity/xml/VersionXMLConverter.java b/src/main/java/caosdb/server/entity/xml/VersionXMLConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..06762c38a8c6503032b14e33f6ee5be702c91ab5
--- /dev/null
+++ b/src/main/java/caosdb/server/entity/xml/VersionXMLConverter.java
@@ -0,0 +1,32 @@
+package caosdb.server.entity.xml;
+
+import caosdb.server.entity.Version;
+import java.util.TimeZone;
+import org.jdom2.Element;
+
+class VersionXMLConverter {
+  public Element toElement(Version version) {
+    Element result = new Element("Version");
+    result.setAttribute("id", version.getId());
+    if (version.getDate() != null) {
+      result.setAttribute("date", version.getDate().toDateTimeString(TimeZone.getDefault()));
+    }
+    if (version.getPredecessors() != null) {
+      for (Version p : version.getPredecessors()) {
+        Element predecessor = new Element("Predecessor");
+        predecessor.setAttribute("id", p.getId());
+        predecessor.setAttribute("date", p.getDate().toDateTimeString(TimeZone.getDefault()));
+        result.addContent(predecessor);
+      }
+    }
+    if (version.getSuccessors() != null) {
+      for (Version s : version.getSuccessors()) {
+        Element successor = new Element("Successor");
+        successor.setAttribute("id", s.getId());
+        successor.setAttribute("date", s.getDate().toDateTimeString(TimeZone.getDefault()));
+        result.addContent(successor);
+      }
+    }
+    return result;
+  }
+}
diff --git a/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java b/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java
index d647b64d2d56a8cc073467326d9ecb868b6c7d0f..280b413235198b2e778b7d0bf7d1c99ba2fef54d 100644
--- a/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java
+++ b/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java
@@ -7,7 +7,6 @@ import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.Role;
 import caosdb.server.entity.wrapper.Property;
 import caosdb.server.jobs.ContainerJob;
-import caosdb.server.utils.Utils;
 import java.util.Objects;
 
 public abstract class AWIBoxLoanModel extends ContainerJob {
diff --git a/src/main/java/caosdb/server/transaction/Insert.java b/src/main/java/caosdb/server/transaction/Insert.java
index 18eb5f2ca27fe7c1ddc1ca7bd08a7092baf4e4ff..c1d53f3051eb65efd9d658179e514e13863c313b 100644
--- a/src/main/java/caosdb/server/transaction/Insert.java
+++ b/src/main/java/caosdb/server/transaction/Insert.java
@@ -26,6 +26,7 @@ import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.InsertEntity;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.FileProperties;
+import caosdb.server.entity.Version;
 import caosdb.server.entity.container.InsertContainer;
 import caosdb.server.entity.container.TransactionContainer;
 import caosdb.server.permissions.EntityACL;
@@ -102,10 +103,11 @@ public class Insert extends WriteTransaction<InsertContainer> {
 
   public void insert(final TransactionContainer container, final Access access) throws Exception {
     if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) {
+      execute(new InsertEntity(container), access);
       for (EntityInterface e : container) {
-        e.setVersionDate(this.getTimestamp());
+        // TODO move to InsertEntity transaction
+        e.setVersion(new Version(e.getVersion().getId(), this.getTimestamp()));
       }
-      execute(new InsertEntity(container), access);
     }
   }
 
diff --git a/src/main/java/caosdb/server/transaction/Update.java b/src/main/java/caosdb/server/transaction/Update.java
index 6a48aaac361b510b1103d3a286991b45bc40d694..b9e6e8de19f137014d10d1c6516c07ca2acabf8e 100644
--- a/src/main/java/caosdb/server/transaction/Update.java
+++ b/src/main/java/caosdb/server/transaction/Update.java
@@ -170,9 +170,6 @@ public class Update extends WriteTransaction<UpdateContainer> {
 
   private void update(final TransactionContainer container, final Access access) throws Exception {
     if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) {
-      for (EntityInterface e : container) {
-        e.setVersionDate(getTimestamp());
-      }
       execute(new UpdateEntity(container), access);
     }
   }