NAME
git-annex undo - undo last change to a file or directory
SYNOPSIS
git annex [filename|directory] ...
DESCRIPTION
When passed a filename, undoes the last change that was made to that file.
When passed a directory, undoes the last change that was made to the contents of that directory.
Running undo a second time will undo the undo, returning the working tree to the same state it had before. To support undoing an undo of staged changes, any staged changes are first committed by the undo command.
Note that this does not undo get/drop of a file's content; it only operates on the file tree committed to git.
OPTIONS
--jsonEnable JSON output. This is intended to be parsed by programs that use git-annex. Each line of output is a JSON object.
--json-error-messagesMessages that would normally be output to standard error are included in the JSON instead.
The git-annex-common-options(1) can also be used.
SEE ALSO
git-annex(1)
AUTHOR
Joey Hess id@joeyh.name
Warning: Automatically converted into a man page by mdwn2man. Edit with care.

Hello,
Context
Thank you for git-annex. I'm progressing in learning how to use it. Seems to work as intended with only annexed files.
I actually need mixed content repository and like the idea of
annex.largefilesdeciding which files go into the annex.While experimenting with mixed content repository, I had
git-annex-undodestroy information twice. Or perhaps I did something wrong?What happened
Here's my .gitattributes
I had a directory (say,
newdir) with some jpg and some other files, not known by git or git-annex so far.Based on https://git-annex.branchable.com/tips/largefiles/ I expected both
git addandgit annex addto add NEF JPG jpg to the annex, and other files as regular git files.In case of problem, I expected
git annex undoto revert state to the one just before the last command (which is: full of my regular files, not symlinks or empty).git add newdiradded them all as regular files, not partly in the annex as expected. Surprised, I wanted to undo and try another command.git annex undoemptiednewdircompletely. Wow! Fortunately these were copies, else they would have been gone forever! To be fair I have not checked at that point if files had been copied in annex, which as only copy would still be a mess because file names would have been lost anyway.I used
git reset <hash>to revert state git-style, checked withgit statusthat state was indeed back to pre-add (newdir empty, not known to git), then copied the files again from their source.git annex add newdiradded them all as annexed files, replacing with links, not partly as regular files as expected.git annex undoemptiednewdircompletely. I expected my regular files back in place.I had the intended result by using
git addon regular files andgit annex addto add files to be annexed. As if.gitattributeswere absent.git-annex compiled on Debian unstable as of 2016-10-13 from git source, commit 3135d35094aa5453ef7a5f12762e00e0139a6dbb.
Questions
git annex addbehave as intended by you? Wasn't it supposed to automatically decide which files go to the annex?git annex undobehave as intended by you? Wasn't it supposed to revert working directory to the state just before the wrong "add"?.gitattributes,addcommands correctly?Thank you.
Adding this to
.gitattributes:Causes
git-annex addto behave as expected. Questions aboutgit annex undobehavior remain.git annex undoundoes the last change that was committed to the file. If the file has staged changes,git annex undofirst commits those changes (to avoid losing data) and then undoes that commit.The reason that
git annex undodeleted the files from your working tree is that the previous commit did not have those files in it, and it undid to the state at that commit.So, you will never lose the content of a file by running
git annex undo. Ifgit annex undodeletes a file, you can always get it back by checking out a previous version of the branch. Or even by runninggit annex undoa second time, to undo the undo.Hello Joey.
Thank you for your answer. It makes things clearer. I believe the documentation should reflect it.
Where the bug (1) is: not defining the level of operation
Ah, committed. That's an important information. It's not at all what I expected from reading the page.
I was expecting tree-level undo, not commit-level undo. I've found the bug: The documentation for git-annex undo does not define "undo" or the level at which it operates.
Suggestion (1): define the level of operation
What if the documentation included something like this?
Case (2) of staged changes
This sounds strange.
So, if I call git-annex-undo to undo a commit A, but there are staged changes, git-annex-undo will add a commit B then add another commit C to undo B?
This will not undo A.
What use case where you thinking of?
Case of staged changes: suggestion (2)
Perhaps in case when file has staged changes, it would be better to display a warning message, perhaps with a
--commit-stagedoption to bypass it.Internal rationale: got it
Ok I understand the data was not lost. But this kind of reasoning is only reachable when one knows what git-annex-undo really does. So, this command is still dangerous to the unsavvy. Perhaps document that?
Issue (3): What was actually needed (all this time)
It seems that what I really needed was git-annex-unannex.
Suggested changes to documentation (3)
Perhaps in case when file has staged changes, it would be better to display a warning message and suggest using git-annex-unannex instead?
Conclusion
What do you think about the 3 issues and fix suggestions?
Thanks again.
git-annexhas started to become useful here.