Mercurial tips for developers: subrepositories, finding a deleted file and a lot more
Here are my Mercurial tips for individual developers:
Basic configuration
Linux with Gnomeini
[ui]
username = Firstname Surname <[email protected]>
merge = meld
[extensions]
hgext.extdiff=
hgext.bookmarks =
hggit =
[extdiff]
cmd.vdiff = meld
<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px; white-space: normal;">[/codesyntax]</span>
MacOSX
See this guide.
Windows
Use WinMerge.
Find a deleted file
hg log --template "{rev}: {file_dels}n"
Using find in Windows:
hg log --template "{rev}: {file_dels}n" | find /n "filename"
(From Stackoverflow.)
Useful variations of basic commands
General optionsMost hg commands support the --dry-run parameter which is useful for testing what would happen without actually doing anything:
-n, --dry-run (do not perform actions, just print output)
Log and status commands
hg log -r tip (tip changelog)
hg log -l 5 (last 5 changelog statuses)
hg status -m (show modified files only)
hg status -r (show removed files only)
hg status -a (show added files only)
Add, remove, file renames (addremove)
hg remove --after (mark all deleted files as really removed)
hg addremove --similarity 100
(automatically detect files that are 100% similar as renamed)
Commit, push, pull
hg commit -m "commit message" (commit without triggering the editor)
hg push --debug -v ssh://[email protected]/usernamehere/reponamehere
(verbose output for a push to deter the impatient from cancelling)
Grep
hg grep PATTERN
By default, grep only prints output for the first revision of a file in which it finds a match:
--all print all revisions that match and
-i, --ignore-case to ignore case
Reverting to an old revision
Use update to do this for the whole repository:
hg update -r REVISION
If you are fine with clobbering the existing files, use:
hg update -C REVISION
Use revert to do this for an individual file:
hg revert -r REVISION FILENAME
You can also use -d to revert or update to the version that was last committed on a particular date.
Implementing subrepositories
Subrepositories are useful for things like libraries within a project, if you want to maintain a library repo separately from the rest of the code.There are three different options for working with subrepositories:
- Use the subrepos functionality built into Mercurial.
- Pros: built in.
- Cons: sparsely documented and not feature-complete (see Caveats here).
- Link: http://stackoverflow.com/questions/2083393/mercurial-subrepos-how-do-you-create-them-and-how-do-they-work
- Use symlinks.
- Pros: uses core Mercurial features, built into OS (Linuxes but also Windows), possibly more flexible than normal solution, Mercurial will treat symlinked directories just like regular directories.
- Cons: Mercurial will treat symlinked directories just like regular directories.
- Use a bash script and an ignore file to create subrepos.
- Pros: uses core Mercurial features.
- Cons: script involves renaming stuff temporarily.
- Link: http://rustyklophaus.com/articles/20100124-SubmodulesAndSubreposDoneRight.html
How to setup the symbolic links:
You can do this simply by moving the library files to another directory, starting a new repo (if you want the history, see the next tip) and then creating symlinks from the original location back to the new repository location. On Windows, you can use Junction Link Magic for the symbolic links.
Benefits:
The main benefit is that I can flexibly select a couple of key directories to include in the main project, while keeping the side project with its own repo.
The main repository will store the subrepo files as they were at the time of commit, and subrepository can have more detailed history than main repository. This has the benefit of being able to store the state of the whole project, while still doing more granular updates on the subrepo between main repo commits.