Git line ending configuration

Every now and then we get issues from customers with corrupt files, especially DTM files. The issues in these cases is mostly the version control system Git and the line ending configuration.

Background: Line endings

When you write a new line in a code file, you just see the text written on another line. In the background, there are invisible control characters, which tell the editor, to display the text on another line.

Some text editors, such as e.g. Notepad++, have an option to show these hidden characters, which can be helpful in some cases.

Here’s an example of a file with displayed control characters and without.

Historically, there are various kinds of line ending styles.
Windows uses a combination of carriage return CR and line feed LF.
Linux uses only line feed LF

Mor info can be found on the internet, e.g. on Newline - Wikipedia

Line End Configuration (autocrlf)

Git has a configuration option to automatically adjust line endings on commit. If this configuration is set, all line endings will be converted to LF internally in the repository. Files with Windows style CRLF line endings will be converted during commit. When cloning the repository on a Windows client, Git will also automatically convert all LF line endings to CRLF even if the original file which was committed had LF line endings.

In some cases, it is possible that files get corrupted by this setting, because e.g. checksums are not valid anymore.

This is a client setting, which must be set on each git client. Most git clients have a checkbox in the installer to deactivate this configuration, but unfortunately the default is mostly set to on.

Effects

Issues with the settings can lead to strange behavior, where things work well on the working copy of the person who initially committed the file, but people who clone the project have issues with build errors, invalid configurations, checksum errors… In B&R PLC projects, specifically DTM files may get corrupted.

How to prevent

Generally, this is a client setting, which must be disabled for each client. This can be done either in the installer, or later on in the git command line, by using the command
git config --global core.autocrlf false
Sadly, this cannot be stored in the main repository and therefore must be set on all Git clients.

Another, more safe option, is to add a Git attributes file. In a Git attributes file, it is possible to define rules for various file types and Git operations. I would strongly recommend this option.

The only thing you have to do, is placing a file with the name .gitattributes in the root of your git working copy.

image

The file contents could look like this:

# Use gitattributes to deactivate line ending conversion, as this may corrupt some files
# See:
# https://community.br-automation.com/t/git-line-ending-configuration/4073
# https://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
# https://git-scm.com/docs/gitattributes

# Set all files to not make automatic conversion
* -text

IMHO I would recommend to not use any automatic end of line conversion, as there is always a risk of corrupting something. Git should be responsible for version control, but not for formatting files.

7 Likes

If you already have a repository which was created / used with the wrong settings, there are options to migrate these repositories.

How to migrate

See also:

In the following steps I mention SourceTree as a Git client. Of course, it is also possible to use another client, such as VS Code or the Git command line.

If you are using Git submodules, these steps must be done in all submodule folders.

Repository migration

The following steps are required for migrating a repository to the new setting. If you already have corrupted files in some persons working copies, make sure to execute the step from a working state (e.g. the person with the correct DTM files).

  1. Close IDE to prevent automatic background file adjustments during Git operations.

  2. Make sure all other developers have their changes committed and pushed.

    • The migration will create a huge commit with almost all files changed. It is hard to merge such a change, if there are unmerged copies.
  3. Pull and merge the newest state. Make sure there are no uncommitted changes.

  4. Add .gitattributes file as seen in the initial post

  5. Renormalize files
    Renormalizing will check all the files and detect if a line ending was adjusted by autocrlf. If so, it will add the files with the line endings from the working copy.

    1. Open Git Bash in the working copy and execute:

      git add --renormalize . Do not forget the dot at the end of the command! This will add all files with the current line ending of the working copy to the stage

    2. Check and commit the changes in SourceTree

  6. Push changes

7 Likes

thanks Patrick :slight_smile: