def merge(adata, ldata, copy=True):
    if 'spliced' in ldata.layers.keys() and 'initial_size_spliced' not in ldata.obs.keys(): set_initial_size(ldata)
    elif 'spliced' in adata.layers.keys() and 'initial_size_spliced' not in adata.obs.keys(): set_initial_size(adata)
    common_obs = adata.obs_names.intersection(ldata.obs_names)
    common_vars = adata.var_names.intersection(ldata.var_names)
    if len(common_obs) == 0:
        clean_obs_names(adata)
        clean_obs_names(ldata)
        common_obs = adata.obs_names.intersection(ldata.obs_names)
    if copy:
        _adata = adata[common_obs].copy() if adata.shape[1] >= ldata.shape[1] else ldata[common_obs].copy()
        _ldata = ldata[common_obs].copy() if adata.shape[1] >= ldata.shape[1] else adata[common_obs].copy()
    else:
        adata._inplace_subset_obs(common_obs)
        _adata, _ldata = adata, ldata[common_obs]
    same_vars = (len(_adata.var_names) == len(_ldata.var_names) and np.all(_adata.var_names == _ldata.var_names))
    if len(common_vars) > 0 and not same_vars:
        _adata._inplace_subset_var(common_vars)
        _ldata._inplace_subset_var(common_vars)
    for attr in _ldata.obs.keys():
        _adata.obs[attr] = _ldata.obs[attr]
    for attr in _ldata.obsm.keys():
        _adata.obsm[attr] = _ldata.obsm[attr]
    for attr in _ldata.uns.keys():
        _adata.uns[attr] = _ldata.uns[attr]
    for attr in _ldata.layers.keys():
        _adata.layers[attr] = _ldata.layers[attr]
    if _adata.shape[1] == _ldata.shape[1]:
        same_vars = (len(_adata.var_names) == len(_ldata.var_names) and np.all(_adata.var_names == _ldata.var_names))
        if same_vars:
            for attr in _ldata.var.keys():
                _adata.var[attr] = _ldata.var[attr]
            for attr in _ldata.varm.keys():
                _adata.varm[attr] = _ldata.varm[attr]
        else:
            raise ValueError('Variable names are not identical.')
    return _adata if copy else None