Hedgehog’s Team Development for Sitecore has made Sitecore development with teams a dream. Gone are the days of passing around packages and keeping track of your Sitecore changes in notepad for each commit.

As great as TDS has been, I’ve run into an issue on a couple of projects recently when using TDS with Git that has proven to be a big headache: seemingly random content-length mismatch errors on sync with Sitecore.

An exception occurred while updating Sitecore due to a content-length mismatch.

An exception occurred while updating Sitecore due to a content-length mismatch.

The root cause of the content-length mismatch errors is Git's handling of line endings. This can all be prevented by adding a properly-configured .gitattributes file to your repository as soon as you setup your project, but if your team forgot, you're bound to have some headaches. Fortunately, Hedgehog has announced that TDS will be checking for a correctly-configured .gitattributes file starting in TDS 5.5, but until then we've got to fix this ourselves.

If you're like me, you've probably run into this issue multiple times with your teammates and found a lot of conflicting information online about how to fix it. You may have even taken to manually editing the content-length fields in your .item files yourself. In this article I'll show you how to fix the issue for good and then dive into the root cause.

The Fix

Add a file called .gitattributes to the root of your Git repository, right alongside your .gitignore file. If you've already got one, great. Add the following line and commit the change:

*.item -text

(note: make sure that you add this .gitattributes to all future projects along with your initial commit)

The next step is to make careful note of all of the Sitecore items you've added into TDS as you're going to delete them all from disk. After you've made good notes, navigate into each of your TDS projects in Windows Explorer and delete the sitecore folders. Now in Visual Studio, right click on each of your TDS projects, click Get Sitecore Items, and add your items back into TDS--this will recreate those sitecore folders you deleted and write all of your Sitecore items back to disk. Use Git to help you; when you're finished, you should see only modified files, but no added or deleted files.

Commit the updated items to Git and instruct your team to get latest and sync up. You should see content-length mismatches no more.

Git and Line Endings

Git handles line endings in three different ways:

  1. Checkout Windows-style (\r\n), commit Unix-style (\r) line endings
  2. Checkout as-is, commit Unix-style (\r) line endings
  3. Checkout as-is, commit as-is

If you installed Git for Windows, you were prompted to select how you wanted Git to handle line endings in the installer:

How should Git treat line endings in text files?

If you installed Git using Visual Studio or another tool, this may have been configured automatically for you. You can easily check how Git is configured to handle line endings with the following command:

git config core.autocrlf  

Three possible values will be returned that correspond to the options in the Git for Windows installer above:

  1. true (Checkout Windows-style (\r\n), commit Unix-style (\r) line endings)
  2. input (Checkout as-is, commit Unix-style (\r) line endings)
  3. false (Checkout as-is, commit as-is)

With the first option, Git will change all line endings in your files from Windows-style (\r\n) to Unix-style (\r) just before committing to your repository. When Git checks files out from your repository, it will change all line endings from Unix-style (\r) to Windows-style (\r\n).

With the second option, Git will change all line endings in your files from Windows-style (\r\n) to Unix-style (\r) just before committing to your repository; however, when Git checks out files from your repository, it will not change any line endings. As a result, any files that make their way into your repository with Windows-style line endings will be checked out with Windows-style line endings with this option.

With the last option, Git will not change line endings at all on commit or checkout.

This setting applies to all Git repositories you have on your machine, unless a .gitattributes file is present in a repository to override it. The line you added to your .gitattributes file above, *.item -text, sets the line ending policy for .item files (serialized Sitecore items) to checkout as-is and commit as-is for all users of your repository, no matter how they have configured Git to handle line endings on their machines.

TDS and Line Endings

When you use TDS to add Sitecore items to your repository, TDS serializes your Sitecore items to disk using Windows-style (\r\n) line endings. All fields with content (e.g., plaintext, __Renderings, images, etc.), are written with a content-length value that is calculated based on the presence of two-character, Windows-style (\r\n) line endings.

Notepad++ can show line ending characters.

In the screenshot above, I've opened up a sample item in Notepad++ with end-of-line characters visible. This item has a plaintext field called PlainText with four lines of content. With Windows-style (\r\n) line endings, the total length of the content for this field is 62 as shown.

The Root Cause

The TDS content-length mismatch errors arise when someone configures Git with one of the two "checkout as-is" options and a .gitattributes file isn't present in your repository with a line ending policy for .item files.

Consider what happens when someone adds an item from TDS to the repository with Git set to one of the commit Unix-style line endings options. TDS will serialize the item to disk with two-character, Windows-style (\r\n) line endings and the content-length of all fields will be calculated based on that. When the item is added to the Git repository, all of those Windows-style (\r\n) line endings will be converted to single-character Unix-style (\r) line endings. In fact, Git will show warnings on the command line when this happens:

Git shows warnings when it does line ending conversions.

Users who have Git configured to checkout Windows-style line endings will see no issue--when they check that file out, the line endings will be converted back to Windows-style and all content will match the content-length. However, when someone who has Git set to one of the checkout as-is options checks out the file, they will check it out with single-character, Unix-style line endings. When he or she tries to import the item into Sitecore, TDS will throw the content-length mismatch error because the actual length of the content in the .item file is shorter than the specified content-length due to the shorter line endings.

Summary

It's imperative when working with TDS and Git that you have a .gitattributes file present that is configured to checkout and commit .item files without converting their line endings. It's so important that Hedgehog has baked .gitattributes configuration into TDS 5.5, but until then we're on our own.

It isn't necessary to have all of your team update their Git settings; in fact, even if they do, you may still run into occasional content-length mismatch errors with Rich Text fields if you don't have a properly-configured .gitattributes file present.

Let me know in the comments if this helped you or if you have any questions.

This post originally appeared on the Perficient Microsoft blog.