git-annex is the layer underneath DataLad. Most of the time you’ll interact with it through DataLad — but knowing the underlying commands helps when something goes sideways. This page is a pragmatic primer, not a full manual.
1 Why git-annex for neuroimaging
A plain git repository chokes on large binary files: NIfTIs, DICOMs, derivatives. Cloning a 500 GB study would copy every byte of every revision. git-annex sidesteps this by storing only a content-addressed pointer in git — typically a symlink whose name encodes a hash of the file’s contents. The actual bytes live in .git/annex/objects/ and can be fetched on demand from one or more remotes (another machine, a server, S3, GIN).
The trade-off:
- git is good for small text (code, README, JSON sidecars). Every clone gets everything.
- git-annex is good for large binary blobs. Every clone gets the history but only the content you ask for.
2 Setting up an annex
After a normal git init (or git clone), initialize the annex once:
git init
git annex init "my-laptop" # an optional human-readable name for this cloneYou’ll see a new branch called git-annex — it stores metadata (which content is where), separate from your working branch.
3 Adding files: git add vs git annex add
The difference is where the content lives:
git add notes.md # content goes into git history (good for text)
git annex add sub-01_bold.nii.gz # content goes into .git/annex/objects; git tracks a symlinkAfter either, you still commit normally:
git commit -m "Add subject 01"Rule of thumb: small text files → git add; everything large or binary → git annex add. DataLad’s datalad save makes this choice for you based on file type and size.
4 The unlock / lock lifecycle
Annexed files are stored read-only by default — the working-tree entry is a symlink to a content-addressed object. To edit one:
git annex unlock data.csv # replaces the symlink with a writable copy
# ...edit...
git annex add data.csv # re-locks and ingests the new content
git commit -m "update data.csv"v7/v8 repositories
Modern git-annex repos (v7+) use “adjusted unlocked” mode where files appear as regular writable files (no visible symlinks). The lock/unlock concept still applies under the hood, but day-to-day you’ll usually edit files directly and let
git annex addordatalad savere-ingest them.
5 Fetching and dropping content
The defining git-annex commands. After cloning, you have pointers but no content:
git annex get sub-01/ # download content from a remote
git annex get . # everything
git annex drop sub-01/func/*_bold.nii.gz # delete local content; pointer staysdrop is safe by default — it refuses to remove the last copy of a file. git-annex keeps a count of how many remotes have each blob (numcopies, default 1).
To push content to another remote:
git annex copy --to=origin sub-01/
git annex move --to=archive sub-01/ # copy + drop locally6 Remotes and special remotes
A git-annex repo can have multiple remotes. Beyond ordinary git remotes (another git-annex-aware repo, e.g. GIN), git-annex adds special remotes that store content in non-git backends:
datalad— fetch content from any URL DataLad knows aboutS3/glacier— Amazon storagersync— a plain rsync targetdirectory— a local or mounted folder (great for an external drive)
Add one:
git annex initremote backup type=directory directory=/mnt/external/annex encryption=none
git annex copy --to=backup .7 Syncing metadata
Pushing content moves bytes; syncing moves the metadata (which file lives where) across remotes:
git annex sync # exchange metadata with all remotes
git annex sync --content # also push/pull content as neededAfter sync, each clone knows the global state — including which remotes hold which files — even if you haven’t downloaded the content locally.
8 Useful inspection commands
git annex whereis sub-01/func/*_bold.nii.gz # which remotes hold this file
git annex info # repo summary, sizes, remotes
git annex find --not --in=here # files whose content is missing locally
git annex unused # candidate orphans for cleanup9 Moving files out of the annex
Occasionally you’ll annex something by accident — e.g. a CSV that should live in git history. Reverse it with unannex:
git annex unannex *.csv
git commit -am "Move CSV files from git-annex to git"
git pushAfter this, the CSVs are tracked as ordinary git files (full content in history).
10 When to use bare git-annex vs DataLad
- Use DataLad for almost everything in this lab: dataset creation, subject-level fetches, provenance tracking, GIN/GNode sync. See GNode and Datalad.
- Drop down to bare git-annex when you need: a fine-grained
copy --to, a special remote DataLad doesn’t wrap, troubleshooting a stuck dataset, or simply when you want to see what’s actually happening underneath.
See also: Basic Linux Commands for the shell basics, GNode and Datalad for the lab’s main data-versioning workflow.