Search code examples
gitgit-annex

How do I commit in git annex on Windows (adjusted branch)


I have a git and git annex project on a filesystem that does not suppport symlinks. Thus, I have to work with an adjusted branch, that means that on top of my "normal" branch I execute git annex adjust --unlock so that I get a new branch on which my annex'ed files are not symlinks into the annex store, but the original files. My commit tree looks then like this:

  *  git-annex adjusted branch (HEAD, adjusted/master(unlocked))
* ┘ some change (master, refs/basis/adjusted/master(unlocked))
* some prior change
...

When I commit now, I would do so on the adjusted branch I guess, because git-annex cannot create the symlinks, using git annex add MYFILE and git commit`:

  * my new commit (HEAD, adjusted/master(unlocked))
  *  git-annex adjusted branch 
* ┘ some change (master, refs/basis/adjusted/master(unlocked))
* some prior change

What I want is a commit to the master branch that is in the standard git-annex format, meaning that annex'ed files are symlinks to their place in the annex store. Finally, because I cannot have symlinks checked out at my file system, I need to automatically create a new adjusted branch that replaces the symlinks in the commit by the actual files.

So how do I get from the situation above to the following:

  *  git-annex adjusted branch (HEAD, adjusted/master(unlocked))
* ┘ my new commit (master, refs/basis/adjusted/master(unlocked))
│ *  git-annex adjusted branch (abandoned previous HEAD)
* ┘ some change
* some prior change

The git annex manual on git annex adjust only tells me how to get an adjusted branch, but not how to reverse the adjusting. The adjusting concept page is a bit cryptical for me (highlighted text mine).

A user's commits on the adjusted branch have to be reverse adjusted to get changes to apply to the master branch.

This reversal of one adjustment can be done as just another adjustment. Since only files touched by the commit will be reverse adjusted, it doesn't need to reverse all changes made by the original adjustment. [how shall I reverse adjust from files to symlinks when my filesystem doesn't support them?]

For example, reversing the unlock adjustment might lock the file. Or, it might do nothing, which would make all committed files remain unlocked. [what do they mean with "might do nothing"? What are the conditions?]


Solution

  • The datalad project have written the function datalad.support.AnnexRepo.localsync() to accomplish this. The core of that function is

    def localsync(self, remote=None, managed_only=False):
        """Consolidate the local git-annex branch and/or managed branches.
        This method calls `git annex sync` to perform purely local operations
        that:
        1. Update the corresponding branch of any managed branch.
        2. Synchronize the local 'git-annex' branch with respect to particular
           or all remotes (as currently reflected in the local state of their
           remote 'git-annex' branches).
        If a repository has git-annex's 'synced/...' branches these will be
        updated.  Otherwise, such branches that are created by `git annex sync`
        are removed again after the sync is complete.
        [...]
        """
        [...]
        cmd = ['sync']
        [...]
        cmd.extend([
            # disable any external interaction and other magic
            '--no-push', '--no-pull', '--no-commit', '--no-resolvemerge',
            '--no-content'])
        self.call_annex(cmd)
        # a sync can establish new config (e.g. annex-uuid for a remote)
        self.config.reload()
        # cleanup sync'ed branch if we caused it
        if not had_synced_branch and synced_branch in self.get_branches():
            lgr.debug('Remove previously non-existent %s branch after sync',
                      synced_branch)
            self.call_git(
                ['branch', '-d', synced_branch],
            )
    

    so the command needed seems to be git annex sync --no-push --no-pull --no-commit --no-resolvemerge --no-content. This might generate special git annex branches whose names start with "synced/...", which might also already be there from a previous sync operation. So this function deletes them if they were not already present beforehand.