Ignoring files

Ignoring files

When we first created a repository, we saw that a file called .hgignore was created. I said that we would revisit the purpose of this file a little later on. It's time to take a look at it.

There are certain types of files that don't need to go into version control, and in fact, in doing so, often causes more problems than it's worth. For these files, it is best to leave them out of version control.

While we could just simply not ever add them, they'll always be hanging around as files that are new and need to be considered. At every step of the way, Mercurial (and all other version control systems, too, by the way) will keep thinking these are new files that should be added.

So in this tutorial, we'll cover what types of files should be ignored, and how to actually ignore them. We'll also cover how to handle a file that was already put into version control that we later decide should be ignored.

Files That Should be Ignored

Certain types of files can and should be ignored. These fall into two categories.

The first category is compiled files. These are any files that can be regenerated by other files. This is especially the case if the file is in a binary format.

If a file is in a binary format, then the diff tool does a terrible job at figuring out what changed, and the entire binary file (even if it is 50MB) will get committed every time. This means your repository will get really big, really fast.

Since these files can be regenerated, it is generally preferable to ignore them and not allow this to happen.

In Visual Studio, for each project that you have compiled, there will be an obj and a bin folder. These two both contain compiled files, and you can safely ignore both of these.

The second category is user-specific files. An example of this is the .csproj.user files that Visual Studio creates. For every C# project that you have in Visual Studio, there will be a .csproj file. Once you've opened the project in Visual Studio, you'll also probably have a second file called .csproj.user. This file doesn't contain project specific information. That went in the .csproj file. Instead, this contains information about how you're using the project within Visual Studio, so that when you reopen the project, it can come back in the same state you last left it.

With a user-specific file like this, everyone on a team will have different settings. You don't want user-specific files like this in the repository because if you and a teammate have different settings, you'll constantly be overwriting the settings of the other person in the repository.

In fact, this very problem is the reason why the .csproj and the .csproj.user files are separated. Microsoft knew this could potentially be a problem, so they designed a file structure that separates the actual project-specific information from the user-specific information.

At the solution level, you'll see a .sln and a .suo file. The .sln file defines the solution, and should be committed. The .suo file is the "solution user object" file and should not be added to version control.

To summarize what files should be ignored in a Visual Studio solution:

  • Commit .sln.
  • Ignore .suo.
  • Ignore the bin folder in every project.
  • Ignore the obj folder in every project.
  • Commit the .csproj file.
  • Ignore the .csproj.user file.

Ignoring Files

Now that we know what files to ignore, let me show you how to actually ignore files. If you've got a new C# project in your working copy, you'll have plenty of choices to choose from (in the list above) but there's probably a safe bet that if you're following the tutorials, you either are just working with random files, or that you've already committed everything to the repository.

If you don't have a file that you can readily ignore right now that isn't already under version control, just create a new .txt file or something, so that you have something to work with. (I'll show you how to fix files that you've already added to the repository in a second.)

To ignore a file, start by choosing Hg Commit from the context menu, like we've done in the past. Then instead of checking the box to add the file, right-click on the file and select Ignore.

This will bring up the Ignore Filter dialog:


This is a dialog that allows you to edit that .hgignore file. In fact, what we're doing could be done by manually editing that file as well. If you hit the Edit File button, you can open it up at any point and see its format, or what it currently looks like. It's a pretty simple file.

The top line is the "ignore filter" that we want to add. In the image above, we're just trying to make sure that ignoreme.txt gets ignored, but you can get quite a bit fancier. For instance, you could do "*.exe" and ignore all .exe files. If you're familiar with regular expressions (something that is well beyond the scope of this tutorial) you can switch from "Glob" mode to "Regexp" mode.

Once you've got the filter set up the way you want, simply hit the Add button. This will add the filter to the list on the left, and any untracked files (files not already added to version control) will show up on the left, but if one of your ignore filters match the file name, they'll go away. So after we add "ignoreme.txt" as an ignore filter, this file goes away from our list:


At this point, you'll want hit the Close button to close the dialog, and commit these changes, like we've done in the past. The change you will see from this is that .hgignore has been modified to include the new filter.

Ignoring Already Tracked Files

There will inevitably come a time when you've committed a file that should have been ignored. At the very least, if you've been following these tutorials in order, there's a reasonable chance that you've already committed some of the files that shouldn't be to the repository, and you'll want to back those out.

(If this hasn't already happened to you naturally, for the sake of learning, either pick a file that is already under version control that you can start ignoring, or create a file specifically for this purpose, and commit it so that you've got a file in version control that can be ignored.)

Since the file is already under version control, the first step is to get it out of version control. This is called "forgetting" the file, and it shouldn't surprise you that there is a menu item in the Mercurial Shell Extensions. Take the file that should be ignored, right-click on it and choose TortoiseHg > Forget Files…. This brings up the Forget Dialog, which you can use to review what you're attempting to make Mercurial forget, but it should be already configured to forget the files you had selected. So go ahead and press Forget at the bottom.

You'll need to perform another commit action (I told you we'd be using this a lot) to make the forget command stick.

At this point, we're only part way done. We've now kicked the file out of version control. (Though, for good or bad, Mercurial knows that this file was under version control once upon a time, and you'll still be able to see it if you go digging around in those earlier revisions.)

Mercurial has now forgotten that it was tracking this file, but that puts it back into the state that it was in earlier, where the file is untracked. It isn't yet ignored. But now at this point, we simply go back and repeat the basic instructions for ignoring a file that we did in the previous section and we're good to go!