Find deleted files in Mercurial repository history, quickly?
Solution 1
using templates is simple:
$ hg log --template "{rev}: {file_dels}\n"
Solution 2
Update for Mercurial 1.6
You can use revsets for this too:
hg log -r "removes('**')"
(Edit: Note the double *
- a single one detects removals from the root of the repository only.)
Edit: As Mathieu Longtin suggests, this can be combined with the template from dfa's answer to show you which files each listed revision removes:
hg log -r "removes('**')" --template "{rev}: {file_dels}\n"
That has the virtue (for machine-readability) of listing one revision per line, but you can make the output prettier for humans by using %
to format each item in the list of deletions:
hg log -r "removes('**')" --template "{rev}:\n{file_dels % '{file}\n'}\n"
Solution 3
If you are using TortoiseHg workbench, a convenient way is to use the revision filter. Just hit ctrl+s
, and then type
removes("**/FileYouWantToFind.txt")
**/
indicates that you want to search recursively in your repository.
You can use *
wildcard in the filename too. You can combine this query with other revision sets using and
, or
operators.
There is also this Advanced Query Editor:
Solution 4
I have taken other answers and improved it.
Added "--no-merges". On large project with dev teams, there will lots of merges. --no-merger will filter out the log noise.
Change removes("**")
to sort(removes("**"), -rev)
. For a large project with over 100K changesets, this will get to the latest files removed a lot faster. This reverses the order from starting at rev 0 to start at tip instead.
Added {author} and {desc} to ouput. This will give context as to why the files was removed by displaying the log comment and who did it.
So for my use case, it was hg log --template "File(s) deleted in rev {rev}: {author} \n {desc}\n {file_dels % '\n {file}'}\n\n" -r 'sort(removes("**"), -rev)' --no-merges
Sample output:
File(s) deleted in rev 52363: Ansariel
STORM-2141: Fix various inventory floater related issues:
* Opening new inventory via Control-Shift-I shortcut uses legacy and potentinally dangerous code path
* Closing new inventory windows don't release memory
* During shutdown legacy and inoperable code for inventory window cleanup is called
* Remove old and unused inventory legacy code
indra/newview/llfloaterinventory.cpp
indra/newview/llfloaterinventory.h
File(s) deleted in rev 51951: Ansariel
Remove readme.md file - again...
README.md
File(s) deleted in rev 51856: Brad Payne (Vir Linden) <[email protected]>
SL-276 WIP - removed avatar_skeleton_spine_joints.xml
indra/newview/character/avatar_skeleton_spine_joints.xml
File(s) deleted in rev 51821: Brad Payne (Vir Linden) <[email protected]>
SL-276 WIP - removed avatar_XXX_orig.xml files.
indra/newview/character/avatar_lad_orig.xml
indra/newview/character/avatar_skeleton_orig.xml
Comments
-
pIjIN about 2 years
You can use
hg grep
, but it searches the contents of all files.What if I just want to search the file names of deleted files to recover one?
I tried
hg grep -I <file-name-pattern> <pattern>
but this seems to return no results. -
pIjIN about 15 yearsI hadn't seen this but you can imagine how it is not exactly "quick" when you have a repository with thousands of revisions and thousands of file deletions.
-
Peter Rowell about 15 yearsA minor tweak to get rid of commits where no deletion happend: hg log --template "{rev}: {file_dels}\n" | grep -v ':\s*$'
-
Richard almost 13 yearsCould someone explain how to use this with grep to find the name of the file you care about, for us newbies? thanks!
-
johndodo over 12 yearsThis command is really simple. It writes the whole repository log using the provided template. In this case it writes revision number and the deleted filed for each revision - you can use grep to find the needed file. Once you have the revision you can use
hg revert -r 123 path/to/the/file.txt
to recover it. Note that you need to specify a revision prior to the one where you deleted the file! (just substract 1) -
Lars Noschinski over 12 yearsThis solution is really slow, if you are a current mercurial, you should go with th revset solution in the other answer.
-
Mathieu Longtin over 12 yearsI'd combine both of those: hg log --template "{rev}: {file_dels}\n" -r "removes('*')". Otherwise, your default hg log template might not show which files were removed.
-
occulus about 12 yearsIt worked really quite fast for me. Do you have a huge repo? What is a "current mercurial"?
-
Derek Mahar about 10 yearsWith a repository of over 150,000 changesets and using Mercurial 2.5.4, I found that
hg log -r "removes('**')"
took significantly longer to find and display the most recently removed files than didhg log --template "{rev}: {file_dels}\n"
. Doeshg log -r "removes('**')"
search the entire repository history before it generates output? -
Derek Mahar about 10 yearsBy "significantly longer", I meant that I had canceled
hg log -r "removes('**')"
after it had been running for over 12 minutes and had not output a single result. On the other hand,hg log --template "{rev}: {file_dels}\n"
output its first page of results in under one minute. -
Derek Mahar about 10 years@LarsNoschinski: I found the opposite. I found that the revset solution took significantly longer to run when applied to a repository having over 150,000 changesets. See my comments stackoverflow.com/questions/1013550/… and stackoverflow.com/questions/1013550/….
-
anton.burger about 10 years@Derek That's a good question, but I don't know the answer. Possibly one for the mailing list?
-
Jesse Glick almost 9 yearsSeems one runs in chronological order, and the other in reverse chronological order, so that could explain the observed difference?
-
Rob I about 8 yearsDoesn't appear to answer the question. I'm cluing on asker's reference to repository history. Your command reports files that have not been deleted from repository, but are missing from the working copy.