Mercurial for Perforce users

(Might also be usable as "Perforce for Mercurial users")

This document focuses on the similarities and differences of Mercurial with Perforce, a popular commercial CentralisedSCM. Some parts of the general discussion about Mercurial and other centralized SCM systems apply here too. Please refer to CvsConcepts for more details.


Perforce is a quite good commercial CentralisedSCM. In Perforce the repository for all users and branches lives on a central server. The command-line utility p4 or a graphical client called p4v is used for communicating with the server and working with local/repository files. Perforce users create a "client" and check files out from the repository to a working directory in their local file system. Perforce requires network access to the central repository (the "depot") in order to perform any operation. It is very fundamental that multiple users can work on the same code at the same time. As a consequence of this files are write protected until they are opened for edit (and thus given an advisory lock), and only changes to the newest version can be submitted to the repository.

By contrast, Mercurial is a DistributedSCM. Each working directory is self-contained and contains the files being worked on as well as a complete Repository. The command hg is used for working with files/repositories. You do not need to be connected to any server in order to perform any operation. You can even share your changes with others without being directly connected - file transfer or email can be used. It is a basic assumption that users (or uses) have their own repository and pulls other changes to it. This one writer / multiple readers design allows files to be edited without coordination with server, and changes to any version can be submitted.


Perforce changelist numbers are similar to Mercurial revision numbers. Perforce repositories are central and common for all users, and the changelist numbers are thus globally unique and used as such. A single Perforce server can be used to manage multiple "depots", and in this case changelist numbers are unique across all the depots managed by the same Perforce server!

Mercurial RevisionNumbers describe the history of a local repository and will thus be different even in repositories which share a part or even all of their change history. To uniquely identify ChangeSets Mercurial uses ChangeSetIDs instead of RevisionNumbers; changeset IDs are hashes of the content and are thus considered unique.

Modules, branching and tagging

Perforce basically knows nothing about branches - but does it quite well anyway. Any file can be branched anywhere in the depot, even though branch specs often are used to specify branching paths. Client specs are used to decide which part of the depot to put in the working directory.


In Mercurial, each WorkingDirectory is a potential "branch". Branches don't have to be anticipated in advance as in Perforce, they just happen naturally if two changesets are based on the same parent changeset (see also Heads). In Mercurial, a changeset can have two parents (in contrast, Perforce doesn't record this information, as all merge and branch operations are file based). It doesn't even matter whether this happens in the same or in different repositories. Mercurial can assign a branch name to a changeset (see NamedBranches), but conceptually, branches can and do exist in a Mercurial repository even if they are not named.

Mercurial can Merge two changesets (not files) by using the hg merge command, which does a p4 integrate and p4 resolve in one step for all files in both Manifests needing a classical file merge. See also the ImergeExtension, which provides a file by file (an incremental) resolve process similar to the one provided by p4 resolve of Perforce. In Mercurial, a revision of a file can have two parent revisions (see Design for how this is technically implemented), which happens if the file had to be merged as a consequence of the hg merge of two Mercurial changesets.


A Perforce tag is a symbolic name for a subset of files at certain revisions in a depot.

A Mercurial Tag is just a symbolic name for a changeset and thus the whole manifest.


In Perforce, a client is a collection of directories that you can check out under one name.

The equivalent Mercurial concept is the Repository. The ForestExtension can be used to something similar to Perforces mapping of arbitrary repository files into a working directory.

Converting a Perforce repository

Conversion from Perforce was added in Mercurial 1.2. See ConvertingRepositories.

The Perfarce extension allows you to pull changelists from Perforce, and to push Mercurial changesets back to it.

Collaborating with other people

With Perforce, the standard way to share changes with other people is that all contributors are licensed users on the same server and simply check them in.

In Mercurial, collaboration is much more flexible. You can share changes in any number of ways, including (but not limited to) the following:

Perforce-to-Mercurial Cheat sheet

This table gives hints to some related Perforce and Mercurial commands or concepts. Some commands are the same. Some commands just use different words or syntax. Some commands have no direct counterpart, so there the relation is kind of "instead you could use this command which does something else".







read-only files, all meta info is in server depot

WorkingDirectory (WD)

plain files and .hg store with dirstate and history


central repository

.hg store

the whole Repository is in each WD


changes to a set of files, depot-global


changes to a set of files, local to .hg store

base version

the version a file is based on

parent version

the changeset a WD is based on


the latest change in a branch, new changes must be based on this


the changeset that happens to have appeared last in .hg store


location in depot dedicated to one project

WD or Head

usually a branch is a WD, but a repo can also contain branches

Working on files

changes are pending in WD until commit

changes are pending in WD until commit

p4 edit

open a file for edit


hg detects automatically

p4 add

add files

hg add

add files

p4 delete

remove files

hg remove

remove files

p4 diff

show diff for files opened for edit

hg diff

show diff for all changed files


external (graphical) diff program


external (graphical) diff program

p4 opened

show scheduled changes

hg status

show scheduled changes


hg status

list unknown files - they should be added or listed in .hgignore


schedule add added and remove removed files

hg addremove

automatic add+remove if not .hgignore'd

p4 integ; p4 delete

move file keeping history

hg rename

move file keeping history

p4 integ

copy file keeping history

hg copy

copy file keeping history

p4 revert

drop all changes, revert to base version

hg revert

restore files content to any version from repo, no meta data changed

p4 revert

drop all changes, revert to base version

hg update -C

drop all meta changes, revert WD to known state

p4 sync

update p4 client to other repo version

hg update

update hg WD to other repo version

Looking in repository

changes nothing

changes nothing

p4 print

show repository file

hg cat

show repository file

p4 annotate

show modification info for each line in a file

hg annotate

show modification info for each line in a file

p4 changes

show history of (branch of) repo

hg log

show history of repo

p4 filelog

show history of file

hg log

show history of file

p4 tag

add a tag for a changeset

hg tag

add a Tag for a changeset

p4 have

show info for client files

hg parent

show parent of working directory

p4 have

show info for client files

hg identify

show info for working directory

p4 have

show info for client files

hg manifest

list files in repo version

p4 files

show info for repo files

hg manifest

list files in repo version

p4 branches

list branch specifications - that is officially related branches

hg heads

show heads, that is changes not merged

p4 describe

show changelist with its changes

hg log -p

show patch-like changelist

Working with repository

all changes are pending until submit

changes local repo immediately - and perhaps WD

p4 client

create a new branch+client from scratch

hg init

create hg WD from scratch

p4 client; p4 sync

create a new workspace for existing repo

hg clone

create copy of a repo and create corresponding WD

p4 client; p4 integ

create a new branch+client based on other

hg clone

create new hg WD/branch based on other

p4 integ; p4 resolve

get changes from other p4 branch

hg pull; hg merge

get changes from other repo

p4 integ

integrate changes from other branch

hg pull; hg merge

get other version from a hg repo and merge with own repo

p4 integ

integrate changes to other branch

hg push

push own repo to other repo - but it is recommended to pull instead

(diff; merge)

can't move changes to other repos - must be done manually

hg bundle

create distributable file with all repo info

p4 sync; p4 resolve

rebase scheduled changes to other repo version


don't mess with uncommitted changes - commit and merge instead

p4 sync

get new changes from central repository

hg pull

get changes from (possibly more central) repository

p4 sync; p4 resolve

get changes from central repo and merge them with local changes

hg pull; hg merge; hg commit

get changes from another repo, merge them, and commit them to local repo

p4 submit

add pending changes to the chain of changesets in branch

hg commit

save changes in own repo, possibly creating new head/"branch"

p4 submit

submit a change to the central repository

hg push

push a set of changes to another (possibly more central) repository

p4 triggers

run commands (send email) when certain events happen

Hooks, NotifyExtension

run commands when certain actions are performed, send email notifications for changes

p4 protect

control user's access


control access to repository

PerforceConcepts (last edited 2013-11-17 01:37:16 by PhilipJagielski)