git-annex/ bare repositories

Due to popular demand, git-annex can now be used with bare repositories.

So, for example, you can stash a file away in the origin: `git annex move mybigfile --to origin`

Of course, for that to work, the bare repository has to be on a system with git-annex-shell installed. If "origin" is on GitWeb, you still can't use git-annex to store stuff there.

It took a while, but bare repositories are now supported exactly as well as non-bare repositories. Except for these caveats:

- `git annex fsck` works in a bare repository, but does not display warnings about insufficient copies. To get those warnings, just run it in one of the non-bare checkouts.
- `git annex unused` in a bare repository only knows about keys used in branches that have been pushed to the bare repository. So use it with care..
- Commands that need a work tree, like `git annex add` won't work in a bare repository, of course.
- However, you can run commands like `git annex copy`, `git annex get`, and `git annex drop` in a bare repository. In a bare repository, these behave as if the `--all` option were used, and so operate on every single version of every single file that is present in the git repository history. The `--branch` option can be used to make these commands only operate on the files referenced by a specified branch.
  For example: `git annex get --branch master`

Here is a quick example of how to set this up, using `origin` as the remote name, and assuming `~/annex` contains an annex:

On the server:

    git init --bare bare-annex.git
    cd bare-annex.git && git annex init origin

Now configure the remote and do the initial push:

    cd ~/annex
    git remote add origin example.com:bare-annex.git
    git push origin master git-annex

Now `git annex info` should show the configured bare remote. If it does not, you may have to pull from the remote first (older versions of `git-annex`).

If you wish to configure git such that you can push/pull without arguments, set the upstream branch:

    git branch master --set-upstream origin/master

comment 8

@scottgorlin bare git repositories cannot in general be detected when looking at a remote, so `git annex sync` picks a behavior that works whether a remote is a bare git repository or not.

A bare repo and a rsync special remote should have pretty similar performance.

Comment by joey — Tue Jul 22 18:11:47 2025
synced/* branches necessary on bare repo?

Are the synced/* branches necessary for a bare repo? Since there is no working directory, can't sync operate directly on the top level branches of choice, and avoid 'branch pollution'? Is it implemented this way just to simplify the code, or ...?

Also wondering if there is a practical difference between a bare repo and an rsync repo (other than storing the metadata, of course) - they both use rsync for transfer, no? Any speed/overhead/other differences to consider when choosing?

For my use case pertaining to question 2 I am using a local ARM NAS which works with the binary (plus S3 or gdrive remotes etc), but I figure why not spin up a private gitlab repo with metadata and no content since I want an off-site backup of the metadata anyways. Does a bare repo on a nas add anything here, vs an rsync remote? Perhaps just rsync is even better to avoid overhead on a tiny/slow NAS?

Comment by scottgorlin — Tue Jul 22 18:11:47 2025
comment 6

Thanks Anarcat. I actually was dealing with a repository in direct mode, not bare mode. Only realised after today encountering one in bare mode, and reading internals. Your method worked too, but

    git annex indirect

would have been quicker I guess.

Comment by https://me.yahoo.com/a/bBy7WkgQicYHIiiyj.Vm0TcMbxi2quzbPFef#6f9f7 — Tue Jul 22 18:11:47 2025
comment 5

Well, no, i don't think they changed, unless i missed something: there shouldn't be a `.git` repository there.

There are various instructions on how to do this online. They do seem to agree with the first comment above.

Personnally, I would just `git clone` to a different repo and `git annex forget` the old one. Unless you have a very complex repository with a lot of files, this is simple enough... You could even use `git annex reinit` to recycle the previous uuid if that's a concern. So in short:

git clone repo.git repo cd repo git annex info --fast # find the UUID of repo.git git annex move --from $UUID git annex reinit $UUID

Then `repo.git` can be removed if you are certain everything is correct in `repo`.

Note that you may want to have backups of everything before you do anything, as usual.

Comment by https://id.koumbit.net/anarcat — Tue Jul 22 18:11:47 2025
Convert bare repository to normal
Just wondering what the right steps are to convert a bare repository to a normal one? The comment above from 2.5 years ago includes the creation of a .git directory, which actually already exists. Have things changed in the mean time?
Comment by https://me.yahoo.com/a/bBy7WkgQicYHIiiyj.Vm0TcMbxi2quzbPFef#6f9f7 — Tue Jul 22 18:11:47 2025
comment 3

Since the two repos git-annex branches have diverged, you need to run `git annex merge` to merge them before you can push that branch.

Of course, `git annex sync` handles all that for you. It can be used against a bare repository as well as a non-bare.

Comment by joey — Tue Jul 22 18:11:47 2025
push fails

These instructions don't work for me, unfortunately.

This step:

    git push origin master git-annex

results in:

    To ssh://my.server.com/home/itz/git/annex.git
     ! [rejected]        git-annex -> git-annex (non-fast-forward)
    error: failed to push some refs to 'ssh://my.server.com/home/itz/git/annex.git'
    hint: Updates were rejected because a pushed branch tip is behind its remote
    hint: counterpart. Check out this branch and integrate the remote changes
    hint: (e.g. 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Versions: git 1:1.9.1-1~bpo70+2 , git-annex 5.20141024~bpo70+1 (both packaged by Debian, same on local and remote)

And yes, I did a pull on the master branch first. Afraid to do anything with the git-annex branch without explicit instruction.

Comment by https://openid.stackexchange.com/user/814e4910-8e9b-4fe5-83ef-ff863c1a7314 — Tue Jul 22 18:11:47 2025
How to convert bare repositories to non-bare

I made a repository bare and later wanted to convert it, this would have worked with just plain git:

    cd bare-repo.git
    mkdir .git
    mv .??* * .git/
    git config --unset core.bare
    git reset --hard

But because git-annex uses different hashing directories under bare repositories all the files in the repo will point to files you don't have. Here's how you can fix that up assuming you're using a backend that assigns unique hashes based on file content (e.g. the SHA256 backend):

    mv .git/annex/objects from-bare-repo
    git annex add from-bare-repo
    git rm -f from-bare-repo

Comment by https://www.google.com/accounts/o8/id?id=AItOawmraN_ldJplGunVGmnjjLN6jL9s9TrVMGE — Tue Jul 22 18:11:47 2025
Comments on this page are closed.