Mercurial Doc

Hg Init: a Mercurial tutorial
Mercurial Frequently Asked Questions


Commit specific files


$ hg comm file_a file_b file_c

same as:

$ hg comm -I file_a file_b file_c


$ hg comm -X file_b

Change last commit

$ hg commit --amend

Note: If the commit which you would like to change has in-/excluded files you must define these files once again!

Undo last commit (not file changes) -> Deprecated

$ hg rollback


A Guide to Branching in Mercurial

Strategie zur Verwendung von branches

The workflow described below are based on Mercurial Workflows: Stable & Default by Steve Losh. Citations are written italic.

Create a new repository within an existing project directory:

$ hg init

If needed create a .hgignore file like described here?.

After doing the first work respectively copying or creating the first files in the project directory:

$ hg add
$ hg comm -m 'init'
$ hg branch stable
$ hg comm -m 'create branch stable'

After that initial procedure: If there is already a new/first revision of the project tag this within the new created stable branch:

$ hg tag v0.1.0

After hg tag ... a new changeset for this action is done automatically.

  • Tags are of the form "v[MAJOR].[MINOR].[BUGFIX]"
  • Tags with a [MAJOR] version of "0" make no guarantees about anything. They are used for alpha/beta versions of the project.
  • An increase in the [BUGFIX] version of a project means "bugs were fixed."
  • An increase in the [MINOR] version of a project means "functionality has been added without breaking backwards compatibility."
  • An increase in the [MAJOR] version of a project means "backwards compatibility has been broken."

Now we should jump back to the default branch where all the cool new features will be done:

$ hg up default

default branch: Non-bugfix (new features) developement

default is the branch where new features and functionality are added.

If new features for a new release are ready switch into stable branch and merge it with default. After this create a new tag like described above.

stable branch: Bugfix developement and Documentation improvements

stable is where bug fixes are added, as well as documentation improvements that don’t pertain to new features.

Each time you make a bug fix in stable you merge it into default, so default is always a superset of stable.

branch depending commands

Offene, noch nicht zusammengeführte Zweige listen

[default] $ hg branches -a
IDs                          321:b423a6eb51a9

Zweige listen

[default] $ hg branches
default                      322:498493efa053
IDs                          321:b423a6eb51a9 (inaktiv)

Zweig schließen

Damit nicht mehr benötigte Zweige auch nicht mehr gelistet werden, kann man diese schließen. Damit sind sie nicht weg... ;-)

Wechselt man später in einen geschlossenen Zweig wird dieser nach einem commit wieder geöffnet.

Dem letzten commit die Option --close-branch hinzufügen:

$ hg commit --close-branch -m "close branch 'new_branch'"
Änderungssatz 212 erzeugt:cf01f2aad293


Reject changes

Mercurial — revert back to old version and continue from there:

Here's the cheat sheet on the commands:

hg update changes your working copy parent revision and also changes the file content to match this new parent revision. This means that new commits will carry on from the revision you update to.

hg revert changes the file content only and leaves the working copy parent revision alone. You typically use hg revert when you decide that you don't want to keep the uncommited changes you've made to a file in your working copy.

hg branch starts a new named branch. Think of a named branch as a label you assign to the changesets. So if you do hg branch red, then the following changesets will be marked as belonging on the "red" branch. This can be a nice way to organize changesets, especially when different people work on different branches and you later want to see where a changeset originated from. But you don't want to use it in your situation.

If you use hg update --rev 38, then changesets 39–45 will be left as a dead end — a dangling head as we call it. You'll get a warning when you push since you will be creating "multiple heads" in the repository you push to. The warning is there since it's kind of impolite to leave such heads around since they suggest that someone needs to do a merge. But in your case you can just go ahead and hg push --force since you really do want to leave it hanging.

If you have not yet pushed revision 39-45 somewhere else, then you can keep them private. It's very simple: with hg clone --rev 38 foo foo-38 you will get a new local clone that only contains up to revision 38. You can continue working in foo-38 and push the new (good) changesets you create. You'll still have the old (bad) revisions in your foo clone. (You are free to rename the clones however you want, e.g., foo to foo-bad and foo-38 to foo.)

Finally, you can also use hg revert --all --rev 38 and then commit. This will create a revision 46 which looks identical to revision 38. You'll then continue working from revision 46. This wont create a fork in the history in the same explicit way as hg update did, but on the other hand you wont get complains about having multiple heads. I would use hg revert if I were collaborating with others who have already made their own work based on revision 45. Otherwise, hg update is more explicit.

hg revert

Via hg revert wird bei folgenden commits kein neuer Head erzeugt. Die verworfenen Änderungen verbleiben im selben Zweig, in dem weitergearbeitet wird.

Auf letzte Revision zurückfallen, momentanen Stand als backup sichern

hg revert --all       # alle Dateien
hg revert any.file    # spezielle Datei

Auf bestimmte Revision zurückfallen, ohne Sicherung

hg revert --all --rev 12 --no-backup

hg update

Via hg update wird bei folgenden commits ein neuer Head erzeugt. Die verworfenen Änderungen verbleiben in einem "toten Zweig".

Auf letzte Revision zurückfallen

hg update -C            # auf letzte Revision zurückfallen

Auf bestimmte Revision zurückfallen

hg update -C -rev 12   # auf spezielle Revision zurückfallen

Remove file from repo but not from workspace

$ hg remove -Af any.file

or remove it and create it subsequent:

$ hg remove any.file
$ hg cat -r -1 any.file > any.file

Open specific revision of a file with vim

Suppose we want open the last revision of a python file:

$ hg cat [FILENAME] -r -1 | vim - +"filetype=python" +"%unfold!"

This will show the last (→ -r -1) revision of [FILENAME] and pipe the result to vim which reads from stdin (→ -) sets the filetype to python (→ +"filetype=python") and open all folds within the file (→ +"%unfold!").

Manage a dotfiles-repo

After init the new repo within the path your dot-/configfiles are located firstly ignore all files which shouldn't be included for reasons of security or files which changes constantly and aren't from interesting. Open a file .hgignore and add by example the following lines:

syntax: glob

Note that etc or home defining pathes in root of the repo. This means if the repo is located within path /home/USER/myconfigfiles the etc/* and home/.config/* defines all files within /home/USER/myconfigfiles/etc/ and all files within /home/USER/myconfigfiles/home/.config/.

Now add explicit the files which should be in the repo:

$ hg add home/.vim
$ hg add .config/awesome
$ hg add .config/awesome/themes

Note there is no way to add recursive pathes cause mercurial is handling with files not with pathes. This means you must add all files within several pathes manually.

Note that a added file within the repo overrules the entries in .hgignore. This means that added files which should excluded from the repo must firstly become its line within .hgignore and secondly removed from the repo. See Remove file from repo but not from workspace for an explanation of how to do this.

Last modified 3 years ago Last modified on Mar 6, 2016, 4:46:15 PM