Project files committed with CRLF vs having LF locally

Issue #2535 resolved
René Görgens created an issue

Hi Scott,

Maybe this is rather a question for the Google forum, but let me try here:

  • Two weeks ago, in a source format project, I retrieved a sizeable amount of metadata (a couple of hundred files) from the connection and committed them to a repo.
  • This week, when reopening the project, Git shows me lots of changes that (as far as I know) definitely weren’t present when I previously closed the project. When I inspect the diff, the only difference is in line separators, with CRLF in the commit but LF in the local file.

    • Git flags this only for 217 files under force-app\main\default\objects, not for other metadata types (applications, classes, flexipages, flows, layouts, permissionsets, reports, reportTypes, triggers)
    • When I roll back these 217 changes (so that files have CRLF) and refresh a single item (a custom field), I can reproduce the change, the item turns blue and has LF instead of CRLF.
  • When I compare another file with the commit version, such as a flexipage, the commit version ALSO has CRLF while the local version has LF, but Git does NOT flag the difference…

  • In the examples I looked at, retrieved files have LF. How did the commits ever come to have CRLF?

    • There is no Git .config [core] setting for autocrlf or for eol

I installed Git via IntelliJ and was never offered a choice such as in https://davemateer.com/2020/01/09/Line-endings-ignore-in-Git

  • I suppose I should do a git config --global core.autocrlf false?
  • I suppose IC retrieves/ stores all files with LF (which would make sense for cross-platform usage) and I have autocrlf on, so inadvertently transformed LF to CRLF during commit? If that were so, lots of IC users would tend to run into this issue initially?
  • Do you have any idea why Git flags only some files as changed whereas apparently all of them have changes in line separators between commit and local? (Maybe you’ve run into this before)

Thanks a lot.

Comments (4)

  1. Scott Wells repo owner

    This isn't really an IC issue so I'm resolving it, but I'll provide a few pointers based on my own experience. You can configure Git to handle line endings in a number of ways, e.g.:

    https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings

    For the most part I leave things as they are and check in with the line endings from the file itself. However, I develop on Windows but have some files--mostly shell scripts--that must be checked in with UNIX-style line endings for them to work properly in Linux-based CI pipelines. For those, I use .gitattributes where you provide the relative file path and the line ending that should be used for the respective file.

    You can also configure the IDE to maintain and preserve line endings for files as follows:

    https://www.jetbrains.com/help/idea/configuring-line-endings-and-line-separators.html

    Hope that helps!

  2. René Görgens reporter

    Thank you Scott.

    I’ve never really paid attention to this; the following is on Windows:

    • In a fresh source format project, the only file having CRLF is .idea/.gitignore, all files created by sf have LF. .idea/workspace.xml also has LF, so the IDE is not being consistent here in the same directory.
    • Without having configured either Git or the IDE for line endings in any way i.e. being on defaults, committed files have CRLF. The only file whose diff is 100 % is obviously .idea/.gitignore (which I usually exclude, just going with plain defaults here). My conclusion being that the default IDE/Git behaviour sets you up for trouble.
    • Locally created files e.g. an Apex class have CRLF by default. If I change the line separator config (https://www.jetbrains.com/help/idea/configuring-line-endings-and-line-separators.html) from System-Dependent to Unix and macOS (\n), the next Apex class has LF. Actually what happens is that both classes now have LF, toggling the setting changes all (?) locally created files but leaves existing files alone. If I am on System-Dependent and refresh an Apex class from the server, then CRLF is changed to LF. Source control tracks that as a file change (prior to any Git config). So System-Dependent plus Git default behaviour set you up for trouble in multiple ways, upon creation it’s CRLF, up refresh it’s LF, upon commit it becomes CRLF.
    • Upon configuring Git with git config --global core.autocrlf true, it still commits LF as CRLF. So in https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings?platform=windows when it says “On Windows, you simply pass true to the configuration” and “# For compatibility, line endings are converted to Unix style when you commit files.", this is not my experience. So the section “Global settings for line endings” in this GitHub documentation seems to be incorrect.
    • Upon configuring Git with git config --global core.autocrlf false, it finally commits LF as LF.

    Summary: to consistently create files with LF and commit them as LF, two key default settings have to be changed in the IDE and in Git, respectively. The IDE and Git (as installed by the IDE) default settings set you up for multiple inconsistencies at every turn and waste your time with overhead.

  3. Log in to comment