Learn how to fix mistakes in Kiln using three different concepts: start over, undo, and remove. Walk through the commands in both git and Mercurial with the video or read the guide that follows the video.

Start Over

If you write a bunch of code on your local machine and you want to scrap it, how do you get back to your last good commit? This is a common question with distributed version control. Use the following commands:

git git reset --hard
mercurial hg update --clean

Any uncommitted files will be reset, letting you start coding again with a clean slate.

Undo

If you find a bug in a changeset that’s buried in your repository history, you want to undo that changeset by applying a new commit that’s the exact opposite of the old changeset.

git git revert <changeset ID>
mercurial hg backout <changeset ID>

To get the changeset ID, grab it from the URL in Kiln or from git log or hg log at the command line. Both commands work pretty much the same, except that with Mercurial, you also have to commit after you run backout.

One of the advantages of undoing a changeset versus modifying your repository’s history (see below) is that the “undo changeset” becomes a part of your repository history. You make a mistake. You fix the mistake. It’s all tracked in version control. This is preferable to modifying history, which isn’t tracked.

Make sure you’re committing granular changesets. Meaning, if you have 3 different bugs to fix, each bug fix should be its own changeset. That way, if you need to backout one changeset, you can backout one without affecting the others.

Remove

Removing changesets from your repository—and other forms of history modification—should not be taken lightly. While these commands are powerful, you have to keep in mind where your changesets have already been pushed. If you’re simply modifying the history of  changesets that are unique to your local repository, you should be fine. However, if you’ve already pushed the changesets elsewhere, history will need to be modified in all repositories that have those changesets. This means either re-cloning the repository or applying the same history modification in the other repositories.

The most common reason to remove a changeset from your history is because it contains sensitive information, e.g. passwords, tokens, etc. If you simply wish to remove the effects of a changeset, use git revert or hg backout instead (see above).

You can remove changesets directly from within Kiln. See Stripping Changesets in Kiln. After the strip completes, make sure to perform the same strip locally or reclone the repository.

git git reset --hard <changeset ID>^
mercurial hg strip <changeset ID>

Git and Mercurial don’t have exact equivalents of strip in Kiln. Mercurial’s command is the same, but git is different. Note the ^ in the git command, which indicates the parent of the specified changeset. In Mercurial, you’re saying “remove this changeset and all its descendants.” In git, because you’re targeting the parent of the changeset, you’re saying, “forgot about all the history of the descendants of the *parent* of the specified changeset.” You could end up removing multiple branches if the changeset has multiple lines of descendants.

For example, let’s say you wish to remove the following changeset, with Mercurial changeset ID ace5a7f8b03e and git changeset ID 0733de811a74:

Changeset-to-remove

Because the parent of the changeset has multiple descendants, different files are going to be removed.

With hg strip ace5a7f8b03e:

hg-strip

With git reset --hard 0733de811a74^:

git-reset

The part of the DAG outlined in blue for each image is the part that would be removed.

NOTE: You can also use git reset --hard changesetId~1, which is the same as git reset --hard changesetId^. If you’re using Windows command prompt, the ^ character won’t work. Consider switching to Powershell or use ~1.

See Also