Tasks extension for mercurial

Tasks are collections of contiguous changesets. A task can be short or long lived, but its information is only available locally. This extension overrides the behaviour of push so that it will not push incomplete tasks by default. A task can be in one of 3 states:

  • new - this task has no changesets only a parent node
  • active - a task with some changesets but not complete
  • complete - a task with some changesets and marked as complete

Use 'hg tasks' to list all new and active tasks. 'hg tasks --all' will show completed tasks along with those that are new and active.

This extension adds two new options to push:

  • --all-tasks will push all tasks including incomplete tasks
  • --completed-tasks will only push completed tasks

Use 'hg update [TASK]' to update to the tip node of a task and set it as current. When a task is set as current, all subsequent commits will be assigned/appended to the task.

If the auto.track.new option is set, newly created tasks will automatically be set as current. Otherwise, you will need to first create the task, and then update to it to make it current.

If the auto.stash option is set, your locally changed tracked files will be stashed when using 'hg update' to another revision.

Example tasks workflow: images/example-workflow-thumbnail.png

enabling the tasks extension

To enable this extension download the tasks.py and save it somewhere on your system. Then edit your config file so that it has something similar to:

      tasks = /my/path/to/tasks.py

optional behaviour

The tasks extension can automatically mark newly created tasks as current if you set the auto.track.new. This will allow you to start work on a task right away. To enable this functionality, add this to your config:

      auto.track.new = True

You can have the tasks extension automatically 'stash' changes to tracked files in your working copy when you are working on a task. This allows you to update to a task, do some work, and then update to another task or node and not lose your changes. This means you can switch your context easily and not worry about committing your files. To enable auto stashing of tasks, add this to your config:

      auto.stash = True


List tasks:

      $ hg tasks
      $ hg tasks --all            # will show completed tasks as well

Create a new task:

      $ hg task mytask
      $ hg task mytask -r 3       # will create new task at revision 3

      $ hg task mytask -r 3:10    # will create new task with parent at rev 3,
                                  # start at rev 4, and end at rev 10

Rename a task:

      $ hg task -m mytask mynewtaskname

Mark a task as current:

      $ hg update mytask

Mark a task as completed:

      $ hg task mytask -c

Delete a task:

      $ hg task mytask -d
      $ hg task mytask --delete

Delete all tasks:

      $ hg tasks -A
      $ hg tasks --delete-all

Delete complete tasks only:

      $ hg tasks -C
      $ hg tasks --delete-complete

Get information on a task:

      $ hg task mytask -i
      $ hg task mytask --info

Resume a completed task (will mark a completed task as not complete):

      $ hg task mytask -u
      $ hg task mytask --resume

Trim revisions off a task:

      $ hg log
         (revision 6 is tagged as mytask)
      $ hg task mytask -t -r 3
      $ hg task mytask --trim --rev 3
      $ hg log
         (revision 2 is tagged as mytask.)

Append revisions to a task:

      $ hg log
         (revision 2 is tagged as mytask.)
      $ hg task mytask -n -r 3
      $ hg task mytask --append --rev 3
      $ hg log
         (revision 3 is tagged as mytask.)

additional push options

This extension changes the behaviour of the 'push' command and adds two new options.

When performing an 'hg push' you will be warned and the operation will abort if you have incomplete tasks in your outgoing changesets. This is to stop you from pushing incomplete work. When this occurs, you can do one of two things:

1. push the incomplete work, use the --all-tasks option:

      $ hg push --all-tasks

2. push only completed tasks (all revisions belonging to an incomplete task will be stripped from the outgoing changesets), use the --completed-tasks option:

      $ hg push --completed-tasks

Note that push ignores tasks that are new (i.e. not complete but have no changesets attached).

Visual example of push behaviour: images/push-behaviour-thumbnail.png

additional outgoing options

The --all-tasks and --completed-tasks options are also added to the 'outgoing' command.

If you don't specify either of these new options and there are incomplete tasks changesets not in your remote repo, the output will be the same except with a warning that some changesets will not be pushed by default.

1. use --all-tasks option to make outgoing report all outgoing changesets with no warnings about changesets belonging to incomplete tasks:

      $ hg outgoing --all-tasks

2. use --completed-tasks option to make outgoing only show changesets that will be pushed when using the --completed-tasks option with the push command:

      $ hg outgoing --completed-tasks

using transplant with tasks

If you have the transplant extensions entabled you can use it as follows:

      $ hg transplant --task mytask
      $ hg transplant -t mytask

using log with tasks

The log command is wrapped to accept task names as an argument and will show only changesets that belong to a particular task.

      $ hg log mytask

using export with tasks

The export command is wrapped to accept a task name as an argument and will then create a patch from the start->end nodes of the given task.

      $ hg export mytask

using patchbomb with tasks

The email command is wrapped to accept a task name as an argument and will then email patches representing each changeset assigned to the given task.

      $ hg email --task mytask

using mq with tasks

The qimport command is wrapped to accept a task name as an argument and will then import all patches in the given task.

      $ hg qimport -t mytask
      $ hg qimport --task mytask

implementation notes

Task information is stored in two files:

      .hg/tasks/tasks              # all task info
      .hg/tasks/tasks.current      # the current task

The file format for the tasks and tasks.complete filesa are as follows:


The state can be one of the following: 0 - new, 1 - active, 2 - complete. The first entry shows a task with 2 or more changesets assigned to it, the second entry is a newly created task with no changesets - only a parent:


The above two tasks were created on the same revision (they share the same parent 2ed12f...) but only task1 has any work done against it.

Task stash information is stored in two files, one holds the diff of the working copy compared to the revision stored in hg, the other is a backup of the dirstate (so that stash will rememember if you did something like 'hg add'):

      .hg/tasks/<task>.dirstate    # copy of .hg/dirstate
      .hg/tasks/<task>.stash       # a git diff of working copy compared to current rev + sha list for all modified files

An example stash file:

      # stash of task task1
      # created 04/03/09 20:34:28
      # addedfile 06f86bc4aae30018fd47fe3dc1dabeea587e7dd4
      diff --git a/addedfile b/addedfile
      new file mode 100644
      --- /dev/null
      +++ b/addedfile
      @@ -0,0 +1,1 @@
      +some text

The stash file is divided into 3 parts. 1) two lines which show the task name and date of stash creation. 2) one or more lines separated by "#-" markers; each one of these lines contains a filename and a sha of the contents. 3) the actual git patch.

request for help/improvements

Code optimizations/recommendations/patches are welcome. I know that this extension does not make the best use of either the Python language or the Mercurial API.


Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.