Mercurial
Mercurial
Mercurial is a free, distributed source control management tool. It efficiently handles projects of any size and offers an easy and intuitive interface
Mercurial - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/Mercurial
- "Mercurial is a cross-platform, distributed revision control tool for software developers. It is mainly implemented using the Python programming language, but includes a binary diff implementation written in C. It is supported on Windows, Unix-like systems including FreeBSD, OSX and Linux. Mercurial is primarily a command line program but graphical user interface extensions are available. All of Mercurial's operations are invoked as keyword options to its driver program hg, a reference to the chemical symbol of the element mercury.
- Mercurial's major design goals include high performance and scalability, decentralized, fully distributed collaborative development, robust handling of both plain text and binary files, and advanced branching and merging capabilities, while remaining conceptually simple. It includes an integrated web interface.
- The creator and lead developer of Mercurial is Matt Mackall. Released under the terms of the GNU General Public License (version 2 or any later version)."
.hgrc
Simple ~/.hgrc:
[ui] username = Kenneth Burgener <kenneth@demo.oeey.com>
~/.hgrc: (%homepath%\.hgrc in windows)
# Mercurial Config for Kenneth Burgener [ui] username = Kenneth Burgener <kenneth@demo.oeey.com> editor = vim [extensions] color = purge = transplant = rebase = mq = graphlog = pager = [pager] pager = LESS='FRX' less
Windows:
[ui] #ssh = "C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -i "C:\Users\kenneth\id_rsa.ppk" #ssh = "C:\Program Files (x86)\PuTTY\plink.exe" -ssh -2 -i "C:\Users\kenneth\id_rsa.ppk" #ssh = C:\Users\kenneth\bin\TortoisePlink.exe -ssh -2 -i C:\Users\kenneth\bin\id_rsa.ppk #ssh = "C:\Program Files (x86)\PuTTY\plink.exe" -ssh -2 -i C:\Users\kenneth\bin\id_rsa.ppk ssh = c:\cygwin64\bin\ssh -i /cygdrive/c/Users/kenneth/bin/id_rsa -l jenkins username = Kenneth Burgener <kenneth@demo.oeey.com> [extensions] color = purge = transplant = rebase = mq = graphlog = pager = # largefiles = [color] mode = ansi [pager] attend = annotate, cat, diff, export, glog, help, log, qdiff, status, tip pager = C:\dev\cygwin\bin\less -FSRX #hg16mode = yes [http_proxy] host = no = user = passwd =
repo .hg/hgrc
[paths] default = https://kiloforce@bitbucket.org/kiloforce/pygamephysics
Mercurial Book
Mercurial: The Definitive Guide - http://hgbook.red-bean.com/
- html, epub, source - http://mercurial.selenic.com/wiki/MercurialBook
- html version - http://hgbook.red-bean.com/read/
- pdf version (from IT eBooks) - http://it-ebooks.info/book/385/
- pdf version (from Pirate Bay) - http://thepiratebay.se/torrent/6915366/
Commands
remote repository
Clone remote repository:
hg clone ssh://kenneth@demo.oeey.com/test hg clone http://demo.oeey.com/test # read only access
incomming
See incoming changes from remote since last update: (aliases: in)
hg incoming
outgoing
See outgoing changes to remote since last update:
hg outgoing hg outgoing [URL] # see changes to specified target
pull
To see the incomming changes:
hg incomming hg inc
Pull incomming changes from remote:
hg pull hg pull -u # pull and update in one command (or --update)
Example of a pull that needs a merge:
$ hg pull pulling from /sysbackup/home/kenneth/test1 searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge)
branches
"There is always one named branch in existence: default. This is normally where mainline development occurs, and is equivalent to trunk in Subversion, or master in git." [1]
List branches:
hg branches
Show current branch:
hg branch
To close a branch after merge: [2]
hg up [BRANCH] hg ci -m 'Closed branch [BRANCH]' --close-branch
To reopen a branch, simply update to the hidden branch and commit a change.
A dirty reopen, which will cause the branch name to be reused: (preferred to not use!) [3]
hg branch -f [OLDBRANCH]
"Named branches have the advantage that they make it easy to distinguish the two branches. They have the disadvantage that they are permanent. Permanent means that you cannot remove the branch name from the changesets on the branch — the name is literally baked directly into the changeset." [4]
"Bookmarks provide a way to have non-permanent branch names, see hg help bookmarks." [5]
tags
Tags - Name a particular revision using <name>. Tags should not change - ever.
hg tag - add one or more tags for the current or given revision
List tags:
hg tags
Tag current revision:
hg tag [TAG_NAME]
bookmarks
Bookmarks - pointers to certain commits that move when committing. Bookmarks are local. They can be renamed, copied and deleted.
"Bookmarks provide a way to have non-permanent branch names" [6]
List bookmarks:
hg bookmarks hg bo # shortest version
Set a bookmark:
hg bookmarks [NAME]
Delete bookmark:
hg bookmarks --delete [NAME] # -d
Rename bookamrk:
hg bookmarks --rename [OLDNAME] [NEWNAME] # -m
tags vs bookmarks
Bookmarks are local only, by default.
tag vs bookmark: [7]
- The biggest difference is that a bookmark is automatically moved forward when you commit.
tag vs bookmark: [8]
- A tag is like as stamp that the editor put on your manuscript to say "ok, we keep a trace of your current work, in case something happens."
- A named branch would be a chapter. You have to choose at one point which chapter you'll have to write, and they are there to stay. Some will merge back, some will end (sorry, you died.)
- A bookmark is, well, a bookmark. It follows you while you're reading (committing) the book. It helps you to keep tracks of "what you were reading at that time", so you can remove them, move them to a different "chapter". When you share the book (push), you usually don't share your bookmarks, unless you explicitly want to. So you usually use them on anonymous branches because their life cycle is shorter than named branches.
---
Remote bookmarks: [9]
- bookmarks on a server will automatically be updated
- a local only bookmarks can be pushed to the server with 'hg push -B [bookmark]'
- once a bookmark exists on both the server and client, then it will auto push too
See what server bookmarks are missing locally:
hg incoming -B
See what local bookmarks are missing from server:
hg outgoing -B
To pull a bookmark from the server:
hg pull -B [BOOKMARK]
To push a bookmark to the server:
hg push -B [BOOKMARK]
To delete a remote bookmark:
hg -d [BOOKMARK] hg push -B [BOOKMARK]
There are actually five concepts to play with: [stackoverflow.com/questions/5385813/whats-the-difference-between-hg-tag-and-hg-bookmark]
- tags
- local tags
- bookmarks
- lightweight branches
- named branches
heads
Show heads:
hg heads hg heads [branch] # show only heads for specified branch
Close out spurious head: (Mercurial: beheading a head)
hg update [head_revision] hg commit -m 'closing spurious heads' --close-branch hg push
Show closed heads:
hg heads --closed
update
Update to branch: (aliases: up, checkout, co)
hg update # update to latest on current branch hg update default # default branch hg update 0.2.15 # 0.2.15 branch hg update null # remove all working files, but keep repo intact (good for servers)
Update to init commit:
hg update null hg update 000000000000 hg update 00
cwd
Update change working directory and report tip version:
hg --cwd esx tip
logs
Show change log:
hg log hg log -v # include changed files hg log -l 1 # limit to last entry hg log -r [REV] -v # show revision details hg log -r [REV]:[REV] -v # show revision details with the revision range hg log -b [BRANCH] # show logs for target branch hg log --rev "ancestors(.)" hg log --rev "reverse(ancestors(.))" # Output in the same order as vanilla hg log hg log -f/--follow # show only current branch related logs
Show current working reivison summary log:
hg summary
Show changes between two branches: [10]
hg log -r "branch('foo') - branch('default')"
diff
Show code changes from working directory to parent revision:
hg diff
Show code changes between two branches: [11]
hg diff -r "ancestor(default, foo)" -r foo
Show changes since previous revision (numerically, possibly not on same branch, sadness). If you use a negative number as a revision it means “X revisions back from the tip revision of the repository”. -1 means the tip itself, -2 means the tip’s parent, and so on.
hg diff -r -2
The -1 says previous changeset on this branch. the '.' means the current changeset. You can use -2, -3 etc, but once you hit a merge point, it gets a little more interesting:
hg diff -r -1:. filename
Others:
hg diff -r -3 -r -2 file
status
Show changes in working folder: (aliases: st)
hg status
Show only modified, added or removed (not untracked or deleted files):
hg status -mar
add
Add file to be tracked:
hg add [file]
If you need to unadd (unwatch) a file, use 'revert' or 'forget'.
forget
If you need to unadd (unwatch) a file:
hg forget [file]
commit
Commit: (aliases: ci)
hg commit -m 'message'
id
Show current changeset hash and revision: (+ indicates changes from checkout)
hg id # hash and branch hg id -n # revision
tip
WARNING: TIP IS USELESS!!!
tip - "show the tip revision"
"The tip revision (usually just called the tip) is the changeset most recently added to the repository (and therefore the most recently changed head)."
What this means - it show the tip of of the repository, not the current branch!
push
Push changes:
hg push # if 'abort: repository is unrelated' something has changed on remote, do pull first. hg push --new-branch # if pushing a new branch hg push -f # if having to force a new head after a branch
Example of a failed push due to missing changes
pushing to /home/kenneth/test1 searching for changes abort: push creates new remote head a5febe590809! (you should pull and merge or use push -f to force)
WARNING: Don't ever force a push. This causes spurious/superfluous heads! Merge first, silly.
paths
paths - "show aliases for remote repositories"
$ hg paths default = /sysbackup/home/kenneth/test1
$ hg paths default /sysbackup/home/kenneth/test1
close a branch
Close a branch: [12]
hg up -C badbranch hg commit --close-branch -m 'close badbranch, this approach never worked' hg up -C default # switch back to "good" branch hg push # push to remote repo if needed
NOTE: This does not delete the branch, just makes it inactive. To see deactivated branches:
hg branches --closed
bare repo
Create a bare remote repository (with only .hg folder):
mkdir test hg init test hg clone test ssh://kburgener@hg/~kburgener/test # ignore 'no changes found' message
If you have updated the server repo, you can clean it back out (to bare repo) with:
hg update null # remove all working files, but keep repo intact (good for servers) hg update 000000000000 hg update 00
clean up and revert
Delete all untracked files: [13]
hg clean hg st -un0 | xargs -0 rm # without purge extension installed
Revert files to last update: (creates .orig files, kill with 'hg clean')
hg revert [file] hg revert . # all files hg revert --all hg revert --all --no-backup # do not create .orig files hg revert . -r -2 # revert all files in current directory to last committed revision, but leave working revision alone.
Complete revert and cleanup: (this won't remove files from the .hgignore)
hg revert . hg clean
archive
Archive - create an unversioned archive of a repository revision: (aka export dump in other CVS)
hg archive [outpath]
merge
Merge branch code into default:
hg update default hg merge [BRANCH]
To close a branch after merge: [14]
hg up [BRANCH] hg ci -m 'Closed branch [BRANCH]' --close-branch
Example of merge failure due to uncommitted local changes:
$ hg merge abort: outstanding uncommitted changes (use 'hg status' to list changes)
Manual Merge:
# method 1: first merge, then revert the file back to the state you want it at: hg merge esx_paramiko hg revert esx.py -r default vimdiff esx.py esx.py.orig hg commit -m 'merged my way'
# method 2: ?
To abort a merge:
hg update -C .
blame
Alias for #annotate
summary
Show current working reivison summary log:
hg summary
See also #logs
annotate
Show user who made last change, line by line:
hg annotate * -u
transplant
Updated .hgrc:
[extentions] transplant =
Push a change from a revision to the current working directory:
hg log -l 1 # get revision from the last submission hg update [BRANCH] # update to branch wanting transplant hg transplant [REV] # transplant revision from other branch to here, including commit hg push # push changes back to main
rebase
rebase - "move changeset (and descendants) to a different branch"
Note: "You should not rebase changesets that have already been shared with others."
Merge vs Rebase: [15]
- "Merging brings two lines of development together while preserving the ancestry of each commit history."
- "Rebasing unifies the lines of development by re-writing changes from the source branch so that they appear as children of the destination branch – effectively pretending that those commits were written on top of the destination branch all along"
- "So merging keeps the separate lines of development explicitly, while rebasing always ends up with a single linear path of development for both branches. But this rebase requires the commits on the source branch to be re-written, which changes their content and their SHAs."
"When contributing to a project, sometimes there is the need to keep some patches private, while keeping the whole repository up-to-date. In those cases it can be useful to "detach" the local changes, synchronize the repository with the mainstream and then append the private changes on top of the new remote changes. This operation is called rebase." [16]
Updated .hgrc:
[extentions] rebase =
Problem: "Every other commit reads some variant of, “Merged with stable,” “merged with base,” or some such. These commits convey no useful information, yet completely clutter your commit history. How do you make your history more useful?" [17]
Solution: "The answer lies in rebasing. Rebasing is a technique made popular by git where you rewrite your not-yet-pushed patches so that they apply against the current remote tip, rather than against the tip of the repository you happened to last pull. The benefit is that your merge history shows useful merges—merges between major branches—rather than simply every single merge you did with the upstream repository." [18]
Example: [19]
hg push # error about new heads hg pull hg rebase hg push
Or simplify with
hg pull --rebase
References:
- Merge or Rebase? | SourceTree Blog - http://blog.sourcetreeapp.com/2012/08/21/merge-or-rebase/
graphlog
Updated .hgrc:
[extentions] graphlog =
hg glog | less
Example:
@ | | o | | o | |/
strip
Strip commits from history - destroy!
hg out hg strip [REV] # repeat for each revision
Requires 'mq' extention
rollback
Able to rollback the last commit (only do this if it hasn't been shared!)
hg rollback
backout
backout - reverse effect of earlier changeset
"Mercurial can backout an old changeset from the past for you. It looks at the changeset, figures out the opposite, and does that to your current working directory. " [20]
hg backout -r [REV] --merge
verify
"Repository Maintenance - The Mercurial repository format ("reflog") is designed to be reliable and efficient. Unlike the git storage format, it does not require ongoing maintenance (such as garbage collection). Since file systems and hard drives are fallible, it is possible that an error could corrupt a repository. To verify the integrity of the repository, run:
$ hg verify
This will perform an extensive series of tests, and report the results." [21]
Show Current Changeset
Checked out changeset revision hash:
# hg id 44459a99be45 tip # hg id -i 44459a99be45 # hg log -l1|grep changeset|cut -d: -f3 # show last in log 44459a99be45 # hg log -l 1 --template '{node|short}\n' # show last in log 44459a99be45 # hg parents changeset: 0:44459a99be45 ... # hg summary parent: 0:44459a99be45 tip ... # hg --debug id -i 44459a99be4594fb78ff19b41fa835d70307d255 # hg parent --template '{node}\n' 44459a99be4594fb78ff19b41fa835d70307d255 # hexdump -n 20 -e '1/1 "%02x"' .hg/dirstate 44459a99be4594fb78ff19b41fa835d70307d255
NOTE: if you get a has with a "+" (44459a99be45+) it is because the working directory has changed from the checked out version.
References:
- Print Current Mercurial Revision Hash? - Stack Overflow - http://stackoverflow.com/questions/2485651/print-current-mercurial-revision-hash
- How do I get the current mercurial revision without calling hg? - Stack Overflow - http://stackoverflow.com/questions/1751944/how-do-i-get-the-current-mercurial-revision-without-calling-hg
- Mercurial: Obtain the current changeset of a particular file - Stack Overflow - http://stackoverflow.com/questions/2378249/mercurial-obtain-the-current-changeset-of-a-particular-file
Binary Data
Options:
- store locally, cluttering up .hg - bad!
- store remotely
- subrepo (like svn) [22]
- #largefiles Extension [23] (This extension is distributed with Mercurial 2.0 and later.)
- bigfile extension
"Handling Large Files - Some projects (games are an excellent example) feature large binary resources, which do not lend themselves well to management under a VCS. Examples include images, movies, sound files, level data, and so on. You don't want to keep multiple versions of these files around if you can help it, and performance can suffer for files over about 10MB. The bigfile extension aims to solve this problem by storing large binary files (Binary Large Objects, or BLOBs) in a separate location, while still allowing you to manage the files using Mercurial." [24]
"SVN doesn't handle binary files much differently, the difference is that with Mercurial you have the whole repository on every system. A diff of a binary file is often the size of the file itself, so clone/push/pull operations can take a long time if there have been many changes to binary files. Solutions might be the bfiles or bigfiles extensions or use a SVN subrepo for any binary files. A minor inconvienence for the many advantages that Mercurial gives for working with code or text." [25]
hg serve
Start server:
hg serve # port 8000 hg serve -p 8080 # port 8080 hg serve -p 8080 -d # daemon mode
Default port is 8000
- "abort: cannot start server at ':8000': Address already in use"
SSL required for commits:
$ hg push pushing to http://demo.oeey.com:8080/ searching for changes remote: ssl required
Allow anyone to update: (requires a restart of the server)
# .hg/hgrc [web] push_ssl=False allow_push=*
References:
- PublishingRepositories - Mercurial - http://mercurial.selenic.com/wiki/PublishingRepositories
- Hg Init: a Mercurial tutorial by Joel Spolsky - http://hginit.com/
hgweb
hgweb.cgi -
"Note that starting with version 1.6 of Mercurial, the hgwebdir.cgi script no longer exists, and its functionality has been merged into the hgweb.cgi script which in most cases can be used with the same configuration." [26]
To setup hgweb to publish a single repository or multiple repositories, perform the following steps:
- Find the necessary script in the root of your Mercurial source tree.
- Copy it to a directory where your Web server can access it. This will be illustrated below using /home/user/webdir as this directory.
- Edit its contents. In particular, you will need to edit it so that it is reading the correct config file.
- Make sure the Web server (such as Apache) is configured and can execute the script.
The hgweb script is provided in more than one form:
- hgweb.cgi is a script for deployment using CGI and is provided in the top-level directory of the source distribution of Mercurial.
- hgweb.wsgi is a script for deployment using WSGI and is provided in the contrib directory in the distribution.
Much better performance can be achieved by using WSGI instead of CGI.
Download latest: http://www.selenic.com/repo/hg-stable/raw-file/tip/hgweb.cgi (pretty minimal script)
- "hgwebdir.cgi (use the one coming with your Mercurial package or download from http://www.selenic.com/repo/hg-stable/raw-file/tip/hgwebdir.cgi)" [27]
Warning: symlinks can cause issues, as hgweb will take the first alphabetical entry found as the official path!
---
/www/hg/hgweb.cgi:
config = "/opt/hg/hgweb.config"
Apache VirtalHost config:
<VirtualHost *:80> ServerName hg.demo.oeey.com #DirectoryIndex hgweb.cgi RewriteEngine On RewriteRule ^(.*)$ /hgweb.cgi/$1 [L,QSA] DocumentRoot /www/hg <Location /> AddHandler cgi-script .cgi Options +ExecCGI AuthType Basic AuthName "HG Repository" AuthUserFile /etc/svn-passwd Require valid-user </Location> ServerAdmin admin@hg.demo.oeey.com ErrorLog logs/hg.demo.oeey.com-error_log CustomLog logs/hg.demo.oeey.com-access_log common </VirtualHost>
/opt/hg/hgweb.config:
[web] motd = <p><small>Hello World</small></p> #baseurl = / # for url rewrite [paths] / = /opt/hg/*
/opt/hg/ken/.hg/hgrc:
[web] description = Ken's Repo contact = Kenneth Burgener <kenneth@demo.oeey.com> #push_ssl = false #allow_push = * #hidden = false
References:
- HgWebDirStepByStep - Mercurial - http://mercurial.selenic.com/wiki/HgWebDirStepByStep
Extentions
Pager
.hgrc:
[extensions] pager = [pager] pager = LESS='FRX' less
or instead of [pager] section use:
export PAGER='less -FRX'
PagerExtension - Mercurial - http://mercurial.selenic.com/wiki/PagerExtension
WARNING: for some reason this extension didn't work on the 'yum install mercurial' version on CentOS 5...
---
For Windows: [28]
[extensions] color = pager = [color] mode = ansi [pager] attend = annotate, cat, diff, export, glog, help, log, qdiff, status, tip pager = C:\dev\cygwin\bin\less -FSRX
Mercurial Queues
[extensions] mq =
MqExtension - Mercurial Queues Extension - Mercurial - http://mercurial.selenic.com/wiki/MqExtension
largefiles
"The largefiles extension allows for tracking large, incompressible binary files in Mercurial without requiring excessive bandwidth for clones and pulls. Files added as largefiles are not tracked directly by Mercurial; rather, their revisions are identified by a checksum, and Mercurial tracks these checksums. This way, when you clone a repository or pull in changesets, only the largefiles needed to update to the current version are downloaded. This saves both disk space and bandwidth." [29]
.hgrc:
[extensions] largefiles =
Usage:
dd if=/dev/urandom of=thisfileislarge count=2000 hg add --large thisfileislarge hg commit -m 'add thisfileislarge, which is large, as a largefile'
References:
- LargefilesExtension - Mercurial - http://mercurial.selenic.com/wiki/LargefilesExtension
convert
"The Convert extension converts repositories from other SCMs (or even Mercurial itself) into Mercurial repositories, with options for filtering and renaming. It can also be used to filter Mercurial repositories to get subsets of an existing one. "
ConvertExtension - Mercurial - http://mercurial.selenic.com/wiki/ConvertExtension
-- convert from git to hg --
Really easy!
hg convert [git_repo] [hg_repo]
-- Split a subdirectory into a separate project --
Split a subdirectory into a separate project - http://mercurial.selenic.com/wiki/TipsAndTricks#Split_a_subdirectory_into_a_separate_project
- Use ConvertExtension with --filemap option.
Filter single folder (and move to top while we are at it):
hg convert --filemap filter.txt sandbox kentank
filter.txt:
include "ken_tank" rename "ken_tank" "."
Enabling clean extension
Add the Mercurial Extension called purge. It is distributed by Mercurial.
This extension adds a “purge” command to “hg” that removes files not known to Mercurial. i.e. untracked Files. So your command would be,
hg purge hg clean # either works
It is not enabled by default, maybe to avoid accidentally removing files that you forgot to add.
To install this extension, add this to your mercurial settings file (.hgrc on Unix, Mercurial.ini on Windows)
~/.hgrc:
[extensions] purge =
Source: How do I delete all untracked files from my working directory in Mercurial? - Stack Overflow - http://stackoverflow.com/questions/1212370/how-do-i-delete-all-untracked-files-from-my-working-directory-in-mercurial
Tutorials
Hg Init: a Mercurial tutorial by Joel Spolsky - http://hginit.com/
- "Mercurial is a modern, open source, distributed version control system, and a compelling upgrade from older systems like Subversion. In this user-friendly, six-part tutorial, Joel Spolsky teaches you the key concepts."
Subrepository
Subrepository - Mercurial - http://mercurial.selenic.com/wiki/Subrepository
WARNING: Requires Mercurial version 1.3 or higher for support!
Create subrepo:
echo conf = ssh://kenneth@demo.oeey.com/mysub > .hgsub hg add .hgsub hg clone ssh://kenneth@demo.oeey.com/mysub mysub
List subrepos:
cat .hgsub
Note: when you update the top repo, it will update all subrepos to match the top repo. If the sub repo needs further updating, it will need to be updated individually:
cd conf hg pull hg update
See changes in subrepo: [30]
hg status -S
How to find out what changeset of main repository contains specified changeset of subrepository: [31]
hg grep hash_you_are_looking_for_blablabla .hgsubstate
hgignore
Note: .hgignore lives in the root directory of a repo.
.hgignore:
.*\.pyc$
Sample: .hgignore:
# use glob syntax. syntax: glob *.pyc *~ # switch to regexp syntax. syntax: regexp ^\.pc/
Note: The default syntax is regexp.
---
Ignore files with not extension: [32]
syntax: regexp ^[^.]+$
ERROR: Does not work, as this will include directories too!
"Because Mercurial matches files and directories top-down while traversing your working copy, and because it doesn't distinguish between files and directories when matching against the patterns in the .hgignore file, you cannot include a directory while ignoring files with the same name."
hgignore whitelist
Ignore all files, except for those in root, and specified folders:
syntax: regexp ^(?!(scripts|foo|bar)/)[^/]+/
This one does work.
mercurial - How can I ignore all directories except one using .hgignore? - Stack Overflow - http://stackoverflow.com/questions/3637496/how-can-i-ignore-all-directories-except-one-using-hgignore
-
Ignore everything, and then manually add what you want:
.*
-
Ignore Extensions - Don't bother. It is broken!
"There is no straightforward way to ignore all but a set of files. Attempting to use an inverted regex match will fail when combined with other patterns. This is an intentional limitation, as alternate formats were all considered far too likely to confuse users to be worth the additional flexibility." [33]
Uses "negative look ahead"
- Whitelist only .py and .txt files: [34] [35] [36]
syntax: regexp ^(?!.*(py|txt)).*$
^some/folder/(?!.*(py|txt)).*$
Note: the above only works for the top level (or specified) directory. Sub directories cause negative failures. See: [37] [38]
References:
- .hgignore - Mercurial - http://mercurial.selenic.com/wiki/.hgignore
- hgignore - http://www.selenic.com/mercurial/hgignore.5.html
Git
Mercurial vs Git
Articles:
- version control - What is the Difference Between Mercurial and Git? - Stack Overflow - http://stackoverflow.com/questions/35837/what-is-the-difference-between-mercurial-and-git
- Git vs. Mercurial: Please Relax « Important Shock - http://importantshock.wordpress.com/2008/08/07/git-vs-mercurial/
- RockStarProgrammer - The Differences Between Mercurial and Git - http://www.rockstarprogrammer.org/post/2008/apr/06/differences-between-mercurial-and-git/
See Git vs Mercurial
Mercurial for Git users
Mercurial for Git users - http://mercurial.selenic.com/wiki/GitConcepts
Mercurial and Git differ only in nomenclature and interface. Git tends to expose more concepts to the user, but gives hints to the user what command might make sense next.
One of the first Git lessons is the repository basic object types: blob, tree and commit. These are the building blocks for the history model. Mercurial also builds up history upon the same three concepts, respectively: file, manifest and changeset.
Command equivalence table - http://mercurial.selenic.com/wiki/GitConcepts#Command_equivalence_table
Git vs Mercurial - WikiVS - http://www.wikivs.com/wiki/Git_vs_Mercurial
Hg-Git Mercurial Plugin
Hg-Git Mercurial Plugin - http://hg-git.github.io/
- "This is the Hg-Git plugin for Mercurial, adding the ability to push to and pull from a Git server repository from Mercurial. This means you can collaborate on Git based projects from Mercurial, or use a Git server as a collaboration point for a team with developers using both Git and Mercurial."
Installation:
pip install hg-git
Add to .hgrc:
[extensions] hgext.bookmarks = hggit =
Usage: (read only)
hg clone git://github.com/schacon/munger.git
Example read/write:
# Github shows "git@github.com:oeey/test.git" hg clone git+ssh://git@github.com/oeey/test.git touch test.txt hg add test.txt hg commit -m 'test' hg push
WARNING: it does not appear to handle HTTPS format, so use "git+ssh":
# hg clone https://github.com/oeey/test.git # ... does not appear to be an hg repository:
Convert Git to Mercurial
Really easy!
hg convert [git_repo] [hg_repo]
Convert Mercurial to Git
cd ~ git clone git://repo.or.cz/fast-export.git git init git_repo cd git_repo ~/fast-export/hg-fast-export.sh -r /path/to/old/mercurial_repo git checkout HEAD
Source: Convert Mercurial project to Git - Stack Overflow - http://stackoverflow.com/questions/16037787/convert-mercurial-project-to-git
Installation
RPMForge Installation
Install RPMForge repo, then:
yum install mercurial
APT
apt-get install mercurial
Manual Installation
Quick install:
#MVER=2.9.1 MVER=3.0 mkdir -p ~/.src ; cd ~/.src wget http://mercurial.selenic.com/release/mercurial-$MVER.tar.gz tar -zvxf mercurial-$MVER.tar.gz cd mercurial-$MVER sudo python setup.py install
Fix path, if needed:
MPATH=$( dirname `which python` ) sed -i 's#\#!/usr/bin/python#\#!/usr/bin/env python#' $MPATH/hg
---
Dependencies: msgfmt in gettext
yum -y install gcc make python python-devel gettext # for python compiled: yum -y install gettext
Optional Dependency: docutils (for python) (fast) - is this even needed any more???
mkdir ~/.src ; cd ~/.src #DVER=0.7 DVER=0.10 wget http://prdownloads.sourceforge.net/docutils/docutils-$DVER.tar.gz?download tar -zvxf docutils-$DVER.tar.gz cd docutils-$DVER sudo python setup.py install # installed to /opt/python26/bin/ # /opt/python26/lib/python2.6/site-packages/docutils-0.7-py2.6.egg-info
See http://mercurial.selenic.com/release/ for release files.
Mercurial Extract:
#MVER=1.4.2 #MVER=1.8.3 #MVER=2.0 #MVER=2.2.2 #MVER=2.2.3 #MVER=2.6.2 #MVER=2.7.2 MVER=2.9.1 mkdir -p ~/.src ; cd ~/.src wget http://mercurial.selenic.com/release/mercurial-$MVER.tar.gz tar -zvxf mercurial-$MVER.tar.gz cd mercurial-$MVER
Now to build and install...
#PYTHON=/opt/python26/bin/python #$PYTHON setup.py clean # not required #$PYTHON setup.py build # not required #sudo $PYTHON setup.py install sudo python setup.py install
Fix hg script to use environment:
MPATH=$( dirname `which python` ) sed -i 's#\#!/usr/bin/python#\#!/usr/bin/env python#' $MPATH/hg
Installs to:
/opt/python26/bin/hg /opt/python26/lib/python2.6/site-packages/mercurial-2.2.3-py2.6.egg-info /opt/python26/lib/python2.6/site-packages/mercurial/* /opt/python26/lib/python2.6/site-packages/hgext/* # commingled with other files!
If /opt/python26/bin/ not in path:
sudo ln -sfn /usr/local/bin/hg /opt/python26/bin/hg
--
Prefix option: -- why would you do this??
/opt/python/bin/python setup.py build sudo /opt/python/bin/python setup.py install --prefix /opt/mercurial
Installs to:
/opt/mercurial/lib/python2.6/site-packages/mercurial/ /opt/mercurial/bin/
---
Build install system wide: (successful with dependency)
make clean && make all && su -c "make install" && hg version
---
Build and install with PREFIX target:
sudo mkdir -p /opt/mercurial sudo chown kenneth /opt/mercurial make clean && make install PREFIX=/opt/mercurial # add to path: ln -s /opt/mercurial/bin/hg /usr/local/bin/hg # test hg version which hg
NOTE: not sure why 'make all' isn't included, but it works
NOTE: tried 'sudo make install' and this failed due to not finding docutils
Add library to Python path (if needed)
export PYTHONPATH=$PYTHONPATH:/opt/mercurial/lib/python2.6/site-packages echo "export PYTHONPATH=\$PYTHONPATH:/opt/mercurial/lib/python2.6/site-packages" >> ~/.bash_profile
---
Local install (this dir)
make local && ./hg version
Other targets:
make clean # clean build make build # don't build doc make install-bin # don't install doc # change install path
Quick Start
Clone a project and push changes
$ hg clone http://selenic.com/repo/hello $ cd hello $ (edit files) $ hg add (new files) $ hg commit -m 'My changes' $ hg push
Create a project and commit
$ hg init (project-directory) $ cd (project-directory) $ (add some files) $ hg add $ hg commit -m 'Initial commit'
Password
NOTE: For SSH access, just use SSH keys.
The following is to remember https passwords.
[auth] bb.prefix = https://bitbucket.org/foo/ bb.username = foo bb.password = foo_passwd
Note: The ‘bb’ part is an arbitrary identifier and is used to match prefix with username and password.
Note: for bb.prefix, just use simple url, not the full one with user name! (eg. bb.prefix = https://bitbucket.org)
References:
- Configuring User Auth for HTTPS / hg tip - http://hgtip.com/tips/advanced/2009-10-01-configuring-user-auth-https/
- hgrc - How to save username and password with Mercurial? - Stack Overflow - http://stackoverflow.com/questions/2584407/how-to-save-username-and-password-with-mercurial
SSH Windows Access
Connect at least one time to save the key:
"C:\Program Files (x86)\PuTTY\plink.exe" -ssh -i "C:\Users\kenneth\private.key" kburgener@hg
mercurial.ini
[ui] ssh="C:\Program Files (x86)\PuTTY\plink.exe" -ssh -i "C:\Users\kenneth\private.key"
Another version using TortoisePlink:
[ui] ssh = C:\Users\kenneth\TortoisePlink.exe -ssh -2 -i C:\Users\kenneth\kmg_id_rsa.ppk
Using Cygwin ssh:
[ui] ssh = c:\cygwin64\bin\ssh -i /cygdrive/c/Users/kenneth/bin/kmg_id_rsa -l jenkins
Clone:
hg clone ssh://kburgener@hg//srv/hg/QA/automation
References:
- AccessingSshRepositoriesFromWindows - Mercurial - http://mercurial.selenic.com/wiki/AccessingSshRepositoriesFromWindows
Issues
requirement dotencode not supported
If an older Mercurial version tries to access a repository that was created by a newer Mercurial version, an error message like
abort: requirement 'dotencode' not supported!
may be displayed, which means the Mercurial version used to access that repository doesn't know how to interpret it, because accessing it would require knowledge about the 'dotencode' capability.
If such an error message appears, a newer Mercurial version must be used to access the repository or the repository must be converted to an older format understood by that version (by using 'hg clone --pull').
The format configuration option may be used to instruct Mercurial to create older repository formats. For example, to convert a 'dotencode' repository into the previous format, the command
hg --config format.dotencode=0 clone --pull repoA repoB
can be used, which of course requires a Mercurial version that supports the 'dotencode' capability.
Source:
- Older Mercurial versions - http://mercurial.selenic.com/wiki/RequiresFile#Older_Mercurial_versions
Error:
# hg pull ... abort: repository is unrelated
Cause:
- somehow the local repository does not match the remote
Solution:
- recheck out repository
abort: push creates new remote head
Error:
# hg push ... abort: push creates new remote head 0c4f58c283a7! (you should pull and merge or use push -f to force)
Cause:
- There was a change made to the remote repo that has not been pulled yet.
Solution #1: merge with your commit
hg pull hg heads # to see new head (fyi) hg merge hg commit -m 'some message' hg push
Solution #2: rollback last commit, update and recommit
# do not pull first, or you can't roll back hg rollback # only can roll back immediate last working command hg pull hg update hg commit -m 'some message' hg push
Solution #3: rebase *favorite* [39]
# hg push hg pull hg rebase hg push
Solution #4: abandon all hope, revert all commits [40]
hg outgoing hg strip [REV] # repeat for each outgoing revision hg pull --update # tricky method: hg strip 'roots(outgoing())'
certificate with fingerprint not verified
Error:
$ hg pull warning: hg.demo.oeey.com certificate with fingerprint 3f:2e:bf:3c:84:f6:78:f5:f3:e2:25:9c:27:8f:c1:f6:17:e3:61:92 not verified (check hostfingerprints or web.cacerts config setting)
Solution: Use the [hostfingerprints] in your .hg/hgrc file.
[hostfingerprints] demo.oeey.com = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
References:
- How to entirely disable SSL certificate checks in Mercurial / TortoiseHg? - Stack Overflow - http://stackoverflow.com/questions/5366869/how-to-entirely-disable-ssl-certificate-checks-in-mercurial-tortoisehg
waiting for lock
Error:
waiting for lock on repository C:\dev\PyDev\workspace\pygamephysics held by 'alienware:5072'
Solution:
- Delete the repository file: .hg/store/lock
- hg recover should be run after a broken locking situation.
Mercurial stuck "waiting for lock" - Stack Overflow - http://stackoverflow.com/questions/12865/mercurial-stuck-waiting-for-lock
Not trusting file
Issue:
Not trusting file /dev/.hg/hgrc from untrusted user root, group dev Not trusting file .hg/hgrc from untrusted user root, group dev
[trusted] users = root groups = dev
mercurial - Not trusting file .hg/hgrc from untrusted user root, group dev - Stack Overflow [41]