developer tip

Git에서 최고의 CRLF (캐리지 리턴, 줄 바꿈) 처리 전략은 무엇입니까?

optionbox 2020. 10. 3. 10:30
반응형

Git에서 최고의 CRLF (캐리지 리턴, 줄 바꿈) 처리 전략은 무엇입니까?


CRLF 끝 줄로 파일을 커밋하려고 시도했지만 실패했습니다.

나는 하루 종일 Windows 컴퓨터에서 다른 전략을 시도하며 Git 사용을 중단하고 대신 Mercurial 을 시도하는 데 거의 매료되었습니다 .

답변 당 하나의 모범 사례 만 공유하십시오.


이 질문을 한 지 거의 4 년이 지난 지금, 마침내 저를 완전히 만족시키는 답을 찾았 습니다 !

자세한 내용은 github : help줄 끝 처리 가이드를 참조하세요 .

Git을 사용하면 파일 텍스트 속성사용하여 리포지토리의 줄 끝 속성을 직접 설정할 수 있습니다 .gitattributes. 이 파일은 저장소에 커밋되고 core.autocrlf설정을 재정의 하므로 git 설정에 관계없이 모든 사용자에 대해 일관된 동작을 보장 할 수 있습니다.

따라서

이것의 장점은 이제 end of line 구성이 저장소와 함께 이동하고 공동 작업자가 적절한 전역 설정을 가지고 있는지 여부에 대해 걱정할 필요가 없다는 것입니다.

다음은 .gitattributes파일 의 예입니다.

# Auto detect text files and perform LF normalization
*        text=auto

*.cs     text diff=csharp
*.java   text diff=java
*.html   text diff=html
*.css    text
*.js     text
*.sql    text

*.csproj text merge=union
*.sln    text merge=union eol=crlf

*.docx   diff=astextplain
*.DOCX   diff=astextplain

# absolute paths are ok, as are globs
/**/postinst* text eol=lf

# paths that don't start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf

편리한 있습니다 .gitattributes 파일을 사용할 준비가의 수집 에서 가장 인기있는 프로그래밍 언어는. 시작하는 데 유용합니다.

를 만들거나 조정 한 후에 .gitattributes는 한 번에 한 번만 줄 끝을 다시 정규화해야 합니다.

있습니다 GitHub의 데스크톱 응용 프로그램이 제안하고 만들 수 있습니다 .gitattributes앱에서 프로젝트의 힘내의 repo를 연 후 파일을. 이를 시도하려면 기어 아이콘 (오른쪽 상단 모서리에 있음)> 저장소 설정 ...> 줄 끝 및 속성을 클릭하십시오. 권장 사항을 추가하라는 메시지가 표시되고 .gitattributes동의하면 앱이 저장소의 모든 파일에 대한 정규화도 수행합니다.

마지막으로, Mind the End of Your Line 기사는 더 많은 배경을 제공하고 Git이 당면한 문제에 대해 어떻게 발전했는지 설명합니다. 나는 이것이 필요한 독서 라고 생각한다 .

팀에 EGit 또는 JGit (Eclipse 및 TeamCity와 같은 도구에서 사용)을 사용하여 변경 사항을 커밋하는 사용자가있을 것입니다. 그렇다면 @gatinueta 가이 답변의 의견에서 설명했듯이 운이 좋지 않습니다.

이 도구는 .gitattributes를 무시하고 CRLF 파일 https://bugs.eclipse.org/bugs/show_bug.cgi? id = 342372

한 가지 트릭은 SourceTree 와 같이 다른 클라이언트에서 변경 사항을 커밋하도록하는 것 입니다. 당시 우리 팀은 많은 사용 사례에서이 도구를 Eclipse의 EGit보다 선호했습니다.

누가 소프트웨어가 쉽다고 말했습니까? :-/


줄 끝을 변환하지 마십시오. 데이터를 해석하는 것은 VCS의 업무가 아닙니다. 데이터를 저장하고 버전 화하기 만하면됩니다. 모든 최신 텍스트 편집기는 어쨌든 두 종류의 줄 끝을 읽을 수 있습니다.


당신 autocrlf=input이 무엇을하고 있는지 정말로 알지 않는 한 당신 은 거의 항상 원합니다 .

아래 몇 가지 추가 컨텍스트 :

It should be either core.autocrlf=true if you like DOS ending or core.autocrlf=input if you prefer unix-newlines. In both cases, your Git repository will have only LF, which is the Right Thing. The only argument for core.autocrlf=false was that automatic heuristic may incorrectly detect some binary as text and then your tile will be corrupted. So, core.safecrlf option was introduced to warn a user if a irreversable change happens. In fact, there are two possibilities of irreversable changes -- mixed line-ending in text file, in this normalization is desirable, so this warning can be ignored, or (very unlikely) that Git incorrectly detected your binary file as text. Then you need to use attributes to tell Git that this file is binary.

The above paragraph was originally pulled from a thread on gmane.org, but it has since gone down.


Two alternative strategies to get consistent about line-endings in mixed environments (Microsoft + Linux + Mac):

A. Global per All Repositories Setup

1) Convert all to one format

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'

2) Set core.autocrlf to input on Linux/UNIX or true on MS Windows (repository or global)

git config --global core.autocrlf input

3) [ Optional ] set core.safecrlf to true (to stop) or warn (to sing:) to add extra guard comparing if the reversed newline transformation would result in the same file

git config --global core.safecrlf true


B. Or per Repository Setup

1) Convert all to one format

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'

2) add .gitattributes file to your repository

echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'

Don't worry about your binary files - Git should be smart enough about them.


More about safecrlf/autocrlf variables


Try setting the core.autocrlf configuration option to true. Also have a look at the core.safecrlf option.

Actually it sounds like core.safecrlf might already be set in your repository, because (emphasis mine):

If this is not the case for the current setting of core.autocrlf, git will reject the file.

If this is the case, then you might want to check that your text editor is configured to use line endings consistently. You will likely run into problems if a text file contains a mixture of LF and CRLF line endings.

Finally, I feel that the recommendation to simply "use what you're given" and use LF terminated lines on Windows will cause more problems than it solves. Git has the above options to try to handle line endings in a sensible way, so it makes sense to use them.


Using core.autocrlf=false stopped all the files from being marked updated as soon as I checked them out in my Visual Studio 2010 project. The other two members of the development team are also using Windows systems so a mixed environment didn't come into play, yet the default settings that came with the repository always marked all files as updated immediately after cloning.

I guess the bottom line is to find what CRLF setting works for your environment. Especially since in many other repositories on our Linux boxes setting autocrlf = true produces better results.

20+ years later and we're still dealing with line ending disparities between OSes... sad.


These are the two options for Windows and Visual Studio users that share code with Mac or Linux users. For an extended explanation, read the gitattributes manual.

* text=auto

In your repo's .gitattributes file add:

*   text=auto

This will normalize all the files with LF line endings in the repo.

And depending on your operating system (core.eol setting), files in the working tree will be normalized to LF for Unix based systems or CRLF for Windows systems.

This is the configuration that Microsoft .NET repos use.

Example:

Hello\r\nWorld

Will be normalized in the repo always as:

Hello\nWorld

On checkout, the working tree in Windows will be converted to:

Hello\r\nWorld

On checkout, the working tree in Mac will be left as:

Hello\nWorld

Note: If your repo already contains files not normalized, git status will show these files as completely modified the next time you make any change on them, and it could be a pain for other users to merge their changes later. See refreshing a repository after changing line endings for more information.

core.autocrlf = true

If text is unspecified in the .gitattributes file, Git uses the core.autocrlf configuration variable to determine if the file should be converted.

For Windows users, git config --global core.autocrlf true is a great option because:

  • Files are normalized to LF line endings only when added to the repo. If there are files not normalized in the repo, this setting will not touch them.
  • All text files are converted to CRLF line endings in the working directory.

The problem with this approach is that:

  • If you are a Windows user with autocrlf = input, you will see a bunch of files with LF line endings. Not a hazard for the rest of the team, because your commits will still be normalized with LF line endings.
  • If you are a Windows user with core.autocrlf = false, you will see a bunch of files with LF line endings and you may introduce files with CRLF line endings into the repo.
  • Most Mac users use autocrlf = input and may get files with CRLF file endings, probably from Windows users with core.autocrlf = false.

I have spent hours to come up with the best possible use of .gitattributes, to finally realize, that I cannot count on it.
Unfortunately, as long as JGit-based editors exist (which cannot handle .gitattributes correctly), the safe solution is to force LF everywhere even on editor-level.

Use the following anti-CRLF disinfectants.

--- UPDATE 2 ---

The dafaults of git client will work in most cases. Even if you only have windows only clients, linux only clients or both. These are:

  • windows: core.autocrlf=true means convert lines to CRLF on checkout and convert lines to LF when adding files.
  • linux: core.autocrlf=input means don't convert lines on checkout (no need to since files are expected to be committed with LF) and convert lines to LF (if needed) when adding files.

The property can be set in different scopes. I would suggest explicitly setting in the --global scope, to avoid some IDE issues described at the end.

git config core.autocrlf
git config --global core.autocrlf
git config --system core.autocrlf
git config --local core.autocrlf
git config --show-origin core.autocrlf

Also I would strongly discourage using git config --global core.autocrlf false (in case you have windows only clients) in contrast to what is proposed to git documentation. Setting to false will commit files with CRLF in the repo. But there is really no reason. You never know whether you will need to share the project with linux users. Plus it's one extra step for each client that joins the project instead of using defaults.

Now for some special cases of files (e.g. *.bat *.sh) which you want them to be checked-out with LF or with CRLF you can use .gitattributes

To sum-up for me the best practice is:

  • Make sure that every non-binary file is committed with LF on git repo (default behaviour).
  • Use this command to make sure that no files are committed with CRLF: git grep -I --files-with-matches --perl-regexp '\r' HEAD (Note: on windows clients works only through git-bash and on linux clients only if compiled using --with-libpcre in ./configure).
  • If you find any such files by executing the above command, correct them. This in involves (at least in linux):
    • change the file
    • revert the change(file is still shown as changed)
    • commit it
  • Use only the bare minimum .gitattributes
  • Instruct the users to set the core.autocrlf described above to its default values.
  • Do not count 100% on the presence of .gitattributes. git-clients of IDEs may ignore them or treat them differrently.

As said some things can be added in git attributes:

# Always checkout with LF
*.sh            text eol=lf
# Always checkout with CRLF
*.bat           text eol=crlf

I think some other safe options for .gitattributes instead of using auto-detection for binary files:

  • -text (e.g for *.zip or *.jpg files: Will not be treated as text. Thus no line-ending conversions will be attempted. Diff might be possible through conversion programs)
  • text !eol (e.g. for *.java,*.html: Treated as text, but eol style preference is not set. So client setting is used.)
  • -text -diff -merge (e.g for *.hugefile: Not treated as text. No diff/merge possible)

--- PREVIOUS UPDATE ---

One painful example of a client that will commit files wrongly:

netbeans 8.2 (on windows), will wrongly commit all text files with CRLFs, unless you have explicitly set core.autocrlf as global. This contradicts to the standard git client behaviour, and causes lots of problems later, while updating/merging. This is what makes some files appear different (although they are not) even when you revert.
The same behaviour in netbeans happens even if you have added correct .gitattributes to your project.

Using the following command after a commit, will at least help you detect early whether your git repo has line ending issues: git grep -I --files-with-matches --perl-regexp '\r' HEAD


This is just a workaround solution:

In normal cases, use the solutions that are shipped with git. These work great in most cases. Force to LF if you share the development on Windows and Unix based systems by setting .gitattributes.

In my case there were >10 programmers developing a project in Windows. This project was checked in with CRLF and there was no option to force to LF.

Some settings were internally written on my machine without any influence on the LF format; thus some files were globally changed to LF on each small file change.

My solution:

Windows-Machines: Let everything as it is. Care about nothing, since you are a default windows 'lone wolf' developer and you have to handle like this: "There is no other system in the wide world, is it?"

Unix-Machines

  1. Add following lines to a config's [alias] section. This command lists all changed (i.e. modified/new) files:

    lc = "!f() { git status --porcelain \
                 | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \
                 | cut -c 4- ; }; f "
    
  2. Convert all those changed files into dos format:

    unix2dos $(git lc)
    
  3. Optionally ...

    1. Create a git hook for this action to automate this process

    2. Use params and include it and modify the grep function to match only particular filenames, e.g.:

      ... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
      
    3. Feel free to make it even more convenient by using an additional shortcut:

      c2dos = "!f() { unix2dos $(git lc) ; }; f "
      

      ... and fire the converted stuff by typing

      git c2dos
      

참고URL : https://stackoverflow.com/questions/170961/whats-the-best-crlf-carriage-return-line-feed-handling-strategy-with-git

반응형