4.5. Commit

Warning

The win32text extension can cause trouble with hunk selection. This has been resolved in Mercurial 1.3 and TortoiseHg 0.8, but requires proper configuration. See issue #82.

The commit tool is one of the two main applications of TortoiseHg. Together with the Repository Explorer (aka, the changelog tool) these two tools can perform or access nearly every function that TortoiseHg supports.

Not only can the commit tool commit your changes, but it can also examine the state of your working directory and perform most routine maintenance tasks (add new files, record renames, manage the ignore filter, etc).

Commit dialog

Commit dialog

4.5.1. Features

At the top of the commit tool is a menu bar, newly introduced in version 0.9.

Tools
Launch common TortoiseHg tools in separate processes
View
Toggle the display of optional features, or refresh the working directory contents.
Operations
These menu items correspond to the toolbar buttons.
Help
Open a web browser to this web page, or launch TortoiseHg About dialog.

Enumerating the toolbar buttons:

Commit
Commit selected diffs in checked files.
Undo
Undo (rollback) last immediate commit. Your commit message will be available in the message history, so you can easily repeat the commit if necessary.
Diff
Visual diff checked files.
Revert
Revert checked files to last revisioned state. If merging, it allows you to select the revert parent.
Add
Add checked files that were in unknown ‘?’ or ignored ‘I’ state.
Move
Move checked files to specified target directory in versioned manner.
Remove
Delete checked unversioned files and/or remove (mark as deleted) any versioned files.
Forget
Forget checked versioned files.
Refresh
Reload the state of the working directory. It tries to retain check and selection state across refresh.
Patch Queue
If the MQ extension is enabled, this toggle button for the patch queue pane will be visible.

Below the toolbar are useful widgets:

Branch dialog
Shows the current branch name of the working directory. Normally this is informational only, but pressing this button opens up a branch maintenance dialog. Do not use this feature unless you understand Mercurial’s named branches.
Recent Commit Messages
A drop-down list of the 10 most recent commit messages. The the drop-down list is filled the first time it is opened.
QNew
If you have enabled the MQ extension, there will also be a text entry for a new patch name. Entering a patch name switches the commit tool into ‘QNew’ mode.

The file list has four columns:

  1. A checkbox that indicates whether the file is selected for an operation. The toolbar buttons only operate on checked files. “Partially” selected files have a special check state. This column header is checkable, it will toggle the file selection states.
  2. The st column holds the status of the file, defined by Mercurial’s status command, one of ‘MARD?IC’. A status of ‘S’ indicates a dirty subrepository that needs to be committed.
  3. The ms column holds the merge state of the file, defined by Mercurial’s resolve command, one of ‘ RU’. See the merge section below.
  4. The canonical path of the file relative to the repository root

Note

If the commit tool was started with a file pattern or selection, a button will appear at the bottom of the file list that can clear the file pattern and give you an unfiltered view of the entire working directory.

Below the file list, inside an expander, are checkboxes that toggle the display of the various classes of files {modified, added, removed, deleted, unknown, clean, ignored}. These check boxes will be disabled if the commit tool was started with a file pattern or selection.

Removed means a revisioned file has been marked as removed. Deleted means a revisioned file is missing but Mercurial has not been told to quit tracking that file. For instance, if you rename a revisioned file in the explorer, the original filename will show up as deleted and the new filename will show up as unknown. By right-clicking on the new filename you can bring up the rename guessing dialog which can discover the rename by comparing file contents and mark the old file as removed and the new file as added while recording the whole operation as a rename.

Unknown files are not tracked by Mercurial, but they also do not match any ignore filters you have configured. Unknown files are shown by default because they are usually files that need to be added to revision control. It is recommended that you keep your ignore filters up to date to ensure that is the case. The context menu of unknown files has an option open the ignore pattern tool.

Clean files are tracked files that have not been modified, while Ignored files are untracked files that match a configured ignore pattern. Neither of those file types are shown by default, unless a the user includes such a file in a selection (explorer) or provides the file name on the command line.

Parent bar

Parent bar in commit dialog

Below both the file list and diff pane is a narrow Parents Bar. This bar shows you the current working directory parent(s), and gives you some warnings if a commit would introduce a new head. The parents bar can be hidden by an option in the View menu.

To the right of the file list is the diff pane. The diff pane is newly tabbed in the 0.9 release.

Text Diff
Shows the textual diffs in the currently selected file.
Hunk Selection
In releases 0.7 through 0.8, this tab was the only content shown to the user. The diffs in this tab can be toggled per “hunk”, allowing the user to cherry pick changes to be included in the commit. As in 0.8, this tab only shows diff hunks for the currently selected file. This tab cannot show binary diffs or renames. That data can only be seen in the Text Diff tab.
Commit Preview
This tab previews all of the selected hunks in every checked file, essentially a preview of what will be committed when you press the commit button.
Patch Contents
Only visible when the commit tool is in QRefresh mode. It displays the current contents of the patch being refreshed.
Advanced bar

Advanced bar in commit dialog

If the Advanced Bar is enabled in the View menu, a bar is inserted between the toolbar and the message history bar. The advanced bar contains:

Committer
The username to use for this commit. This value is usually read from your Mercurial.ini file, but it can be specified on the hgtk command line or read from a patch file. Lastly, the user could manually specify a different username here.
Auto-includes
A text entry that allows the user to modify the comma separated list of files that are always included in the commit list, regardless of whether they have been checked. This is intended for use in repositories that have pre-commit hooks that modify certain files (say a changelog).
Push after commit
A toggle button that determines whether TortoiseHg will attempt to push outgoing changes to your default push target after each successful commit.

4.5.2. Change Selection

So what does the phrase ‘commit the selected diffs in checked files’ mean? Simple, the TortoiseHg commit tool supports change selection intrinsically in the diff browser. This means that all of the changes you make to versioned files can be individually selected to be included in the commit or left out of the commit (but left in the working directory). Fans of darcs or Mercurial’s record extension will recognize this feature immediately.

4.5.2.1. When is this necessary?

When you have more than a single coherent change in your source code and you would like to commit your changes piecemeal. This can often be accomplished by filtering the list of files in each commit, but there will be times when your changes intermingle in the same set of files and that is when this change selection feature becomes indispensable.

4.5.2.2. How does it work?

By double-clicking on individual change hunks in the Hunk Selection tab of the diff panel. Technically, any action which activates a change hunk row will toggle it’s selection status. The spacebar will also work. When a hunk is unselected, the syntax highlighting of the diff is disabled and the background is turned gray. At the same time, the file’s diff header is updated to show the current selection state, the selected hunk count and changed lines will be updated. Toggle the hunk a second time to reselect it for inclusion in your commit.

When a file is partially selected for commit, it’s icon is changed from a checkbox to a radio button. At a glance at the file list, you should be able to find which files are entirely included in the commit, partially included, or entirely excluded.

4.5.2.3. What happens at commit time?

The short answer is that the selected hunks in checked files are committed to the repository and the unselected changes are left in your working directory for the next commit.

The long answer is a little more complicated. What happens behind the scenes is that the files which are partially selected are backed up in a safe location, reverted to their last revisioned state, have their selected change hunks applied back to them, committed, and then finally recovered from backup (thus placing the rejected change hunks back into the working copy). Files which are not partially selected avoid the entire backup, revert, patch, commit, recover round trip and instead are committed in place.

This longer answer is only interesting when something goes wrong, which on Windows unfortunately has a probability greater than 0. If some program (virus checker, compiler) locks your file in the middle of this process you may see an error about a failed patch. These errors are recoverable. Delete any new .rej files left in your repository and retry the commit.

4.5.3. Keyboard navigation

Ctrl-Enter
Trigger the commit
Ctrl-C
When pressed in the diff panel, ctrl-c will copy the currently highlighted (repeat highlighted, not selected) diff hunks to the clipboard. These can be pasted into a text buffer to generate any arbitrary patch based from the changes in your working directory.
Alt-Q
Reflow the paragraph currently under the cursor. You must configure a message format policy for this key combination to work.

The code which copies the hunks to the clipboard is intelligent about diff headers. The clipboard contents will always be a valid patch.

4.5.4. File Context Menus

When right clicking on files in the file list, you will get a context menu of commands that are applicable to the selected files.

For unknown ? files, the context menu will allow you to detect renames (if you think the unknown file is a copy or rename of a revisioned file) or to configure the repository’s ignore filter (if the unknown file should never be revisioned and you want Mercurial to ignore it).

4.5.5. Merging

The commit tool has a special mode when it is opened in a repository that is in a merged state (technically, this means the current working directory has two parent revisions). The file list has no checkboxes and the hunk selection tabs are hidden. The commit ‘manifest’ is essentially immutable, since you must commit the entire working directory after a merge.

The merge state ms column is especially useful in this mode. Files that are marked with R are files where Mercurial and/or the user have successfully merged (resolved) changes from both parents. Files that are marked with U have unresolved changes. You can use the Restart Merge context menu option to restart the merge for those files, or you can use the edit context menu option to resolve the conflict by hand. The Restart Merge menu option allows you to select the merge tool to use to perform the merge, or even to pick one version or the other unconditionally (internal:local, internal:other). After the conflicts have been manually resolved, you must use the mark resolved context menu option to change the file’s merge state to R.

Mercurial will not allow you to commit a merge if any files have unresolved U merge states.

For your reference, local is the revision you had checked out when you started the merge and other is the revision you merged with.

To undo a failed merge attempt, you must tell Mercurial to remove the second parent from your working directory. This usually means performing a clean update of the first parent. The merge tool has an Undo button which does exactly that. The recovery tool also has a Clean button that does the same thing.

Once you have your working directory back at one parent revision, you may restart the merge process.

4.5.6. Commit Message Pane

The commit message pane has these special context menu options:

Paste Filenames:
Paste checked filenames into the commit message at the cursor.
Apply Format:
Apply configured message wrap policy to current message.
Configure Format:
Opens the settings dialog to the Commit tab.

If your project has guidelines for the format of commit messages, you can configure them in the settings tool. The commit tool will enforce your policy at commit time, and you can ask the tool to apply the format to the current message. The Commit tab of the settings tool has these two configurables for commit message policy:

Summary Line Length:
Maximum length of the commit message summary line. If set, TortoiseHg will issue a warning if the summary line is too long or not separated by a blank line. Default: 0 (unenforced)
Message Line Length:
Word wrap length of the commit message. If set, the popup menu can be used to format the message and a warning will be issued if any lines are too long at commit. Default: 0 (unenforced)

4.5.7. Subrepositories

A subrepository is a feature introduced in Mercurial 1.3. It allows one Mercurial repository to store references to external Mercurial (or potentially other VCS) repositories, and to include the state of those external repositories in the main repository’s history.

TortoiseHg 1.0 introduced rudimentary support for subrepositories, and only in the commit / status tool. When Mercurial considers a subrepo as dirty, it will appear in the commit tool as a special entry in the file list with a status of S. If a subrepo is included in the file list of a commit, the subrepo is committed along with the other changes, updating the .hgsubstate file in the main repository root.

Prior to TortoiseHg 1.0, dirty subrepos were not shown in the commit tool and .hgsubstate was not updated during commits.

4.5.8. MQ patches

Many advanced Mercurial users use the MQ extension to manage a patch queue. The commit tool will recognize when a patch is applied and enter patch refresh mode. The title bar will say “refreshing patch patchname” and the patch comment will appear in the commit message pane.

A new ‘Patch Contents’ tab will appear in the diff pane with the full contents of the top patch. The Text Diff and Hunk Selection tabs will show the combined diff of the patch and working directory changes so that you can move changes into or out of the patch during the qrefresh.

This is essentially what the qdiff command would show you. There is, in fact, no way to get just the working copy diffs beyond running hg diff on the command line or typing a name into the QNew entry which toggles the dialog into QNew mode (more below).

The Commit button, which has been renamed QRefresh in this context, will refresh the top patch with the changes you have selected, including the patch description. This may be a bit confusing at first because the changes you leave out of the patch are still going to be in the working directory after the refresh, so unless you look at the patch contents it will not seem as if anything changed.

4.5.9. QNew Mode

The commit tool can be used to create a new patch for your patch queue. If you have the MQ extension enabled, a text entry will be inserted between the branch maintenance button and the message history drop-down box. If you enter a filename in this entry the commit tool will switch out of commit or qrefresh mode into qnew mode. In qnew mode, the commit tool shows only working directory modifications (the changes that would typically get added to a new patch by hg qnew -f). The Commit button will change into a QNew button as well, to make the mode switch more obvious.

When the QNew button is pressed, the selected change hunks are written into a new patch (given the filename you specified), and the dialog is refreshed. After this refresh, the commit tool will obviously switch to qrefresh mode since there will now be at least one applied patch.

You may give the new patch a commit message at the initial qnew event, or you can do it afterwords while in qrefresh mode.

4.5.10. Configurables

Commit ‣ Username
Sets username associated with your commits (see A Quick Start Guide to TortoiseHg)
Commit ‣ Summary Line Length
Configures a ‘policy’ limit for summary lines
Commit ‣ Message Line Length
Configures a ‘policy’ limit for message lines
Commit ‣ Close After Commit:
When set to True, the commit tool will close after a successful commit.
Commit ‣ Default Tab:
The tab on which the status and commit tools will open. 0 - Text Diff, 1 - Hunk Selection, 2 - Commit Preview.

And three other features for advanced users.

Commit ‣ Push After Commit:
When set to True, the commit tool will check the push after commit toggle button on startup.
Commit ‣ Auto Commit List:
Comma separated list of files that are automatically included in every commit. Intended for use only as a repository setting.
Commit ‣ Auto Exclude List:
Comma separated list of files that are automatically unchecked when the status, commit, and shelve tools are opened.
TortoiseHg ‣ Bottom Diffs
Toggles diff pane from left to below file list
TortoiseHg ‣ Max Diff Size
Configures the diff size limit

4.5.11. From command line

The commit tool can be started from command line:

hgtk commit [OPTIONS] [FILE]...

aliases: ci

commit tool

options:

 -u --user  record user as committer
 -d --date  record datecode as commit date

use "hgtk -v help commit" to show global options

For a quick help on the format of date type:

hg help dates