자식 필터 분기로 줄 끝을 수정하려고하지만 운이 없습니다.


270

git의 Windows / Linux 줄 끝 문제에 물 렸습니다. GitHub, MSysGit 및 기타 소스를 통해 가장 좋은 해결책은 로컬 repos가 Linux 스타일 줄 끝을 사용하도록 설정하지만로 설정 core.autocrlf하는 것 같습니다 true. 불행히도, 나는 이것을 조기에 충분히하지 않았으므로 이제는 변경 사항을 가져올 때마다 줄 끝이 지워집니다.

나는 여기서 대답을 찾았다 고 생각 했지만 나에게 도움이되지는 못한다. 내 Linux 명령 줄 지식은 기껏해야 제한되어 있으므로 "xargs fromdos"줄이 그의 스크립트에서 무엇을하는지 잘 모르겠습니다. 해당 파일이나 디렉토리가 존재하지 않는다는 메시지가 계속 표시되고 기존 디렉토리를 가리킬 때 권한이 없음을 알려줍니다.

Windows의 MSysGit과 Mac OS X 터미널을 통해이 작업을 시도했습니다.


이 스레드를 거의 충분히지지 할 수 없습니다. 문제에 대한 최상의 답변을 제공하는 +1 ++
sjas

찰스와 동의하십시오. 그러나 내 경우에는 (맥 OS X 10.8을 사용하여)> 자식 거짓은 없다> 자식 설정 core.autocrlf 입력했다 설정 core.autocrlf
user1045085

답변:


187

gitattributes에 대한 자식 문서는 이제 프로젝트의 모든 줄 끝을 "고정"하거나 정규화하는 또 다른 접근 방식을 문서화합니다. 다음은 요점입니다.

$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status        # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"

정규화되지 않아야하는 파일이 git 상태로 표시되면 git add -u를 실행하기 전에 해당 텍스트 속성을 설정 해제하십시오.

manual.pdf -text

반대로 git이 감지하지 못하는 텍스트 파일은 정규화를 수동으로 활성화 할 수 있습니다.

weirdchars.txt text

이것은 --renormalize2018 년 1 월에 출시 된 git v2.16.0에 추가 된 새로운 플래그를 활용합니다. 이전 버전의 git에는 몇 가지 단계가 더 있습니다.

$ echo "* text=auto" >>.gitattributes
$ rm .git/index     # Remove the index to force git to
$ git reset         # re-scan the working directory
$ git status        # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"

1
의 목적이 무엇인지 말씀해 주 git reset시겠습니까?
crdx

1
git이 인덱스를 재 빌드하도록 강제하는 동안 이진 파일의 바이너리 여부를 추측하기 위해 각 파일을 스캔합니다. rm은 기존 인덱스를 삭제하고 reset은 새 인덱스를 빌드합니다.
Russ Egan

16
고마워, 이것은 나를 위해 일했다. 실행 후 유용한 명령 은 커밋하는 유일한 변경 사항이 줄 끝인지 확인하기 git status위해 실행 git diff --ignore-space-at-eol하는 것입니다.
zelanix

1
참고 :이 솔루션과 "오래된"솔루션 간의 유일한 "실제"차이점은 .gitattributes (적절한 내용 포함)가있는 것입니다. 이것이 git reset없으면 수정을 감지하지 않으므로 쓸모가 없습니다.
Rob

3
gitattributes 페이지 의 지침은 --renormalize2018 년 1 월에 릴리스 된 git v2.16.0에 추가 된 플래그를 활용하도록 업데이트되었습니다. 이 --renormalize플래그는 추적 된 각 파일의 줄 끝을 재 처리하는 프로세스를 단일 명령으로 통합합니다 git add --renormalize ..
Mike Hill

389

이 문제를 해결하는 가장 쉬운 방법은 모든 줄 끝을 수정하는 하나의 커밋을 만드는 것입니다. 수정 된 파일이 없다고 가정하면 다음과 같이 할 수 있습니다.

# From the root of your repository remove everything from the index
git rm --cached -r .

# Change the autocrlf setting of the repository (you may want 
#  to use true on windows):
git config core.autocrlf input

# Re-add all the deleted files to the index
# (You should get lots of messages like:
#   warning: CRLF will be replaced by LF in <file>.)
git diff --cached --name-only -z | xargs -0 git add

# Commit
git commit -m "Fixed crlf issue"

# If you're doing this on a Unix/Mac OSX clone then optionally remove
# the working tree and re-check everything out with the correct line endings.
git ls-files -z | xargs -0 rm
git checkout .

7
추신 : 나는 github.com의 녀석들에게 당신의 픽스를 추천했고 그들은 당신의 솔루션을 사용하기 위해 그들의 헬프 가이드를 업데이트했다 . com / dealing-with-lineendings
Brian Donahue

31
고마워 ... 이것은 훌륭한 수정입니다. GitHub에서 찾았습니다.
PHLAK

4
텍스트가 아닌 파일 (예 : 이진)에서 crlf를 변경하지 않도록 config.safecrlf를 확인할 수도 있습니다. docs kernel.org/pub/software/scm/git/docs/git-config.html 에서 확인하십시오 .
vrish88

4
@ vrish88 : 그러나이 상황이라면 줄 지어있는 엔딩과 core.safecrlf로 인해 어려움을 겪을 가능성이 있습니다. safecrlf를 사용하지 않는 것이 더 쉽습니다. git은 종종 바이너리 파일 감지를 잘못하지 않으며 gitgittribute를 사용하여 바이너리로 수동으로 표시하고 이전 커밋에서 올바른 버전을 복구 할 수 있습니다.
CB Bailey

26
아래 의 Russ Egan의 답변 에서 권장되는 최신 솔루션 은 더 간단하고 모든 소스 코드를 삭제하는 것과 같은 무서운 일을 포함하지 않으므로이 오래된 솔루션은 10 배나 많은 투표를하더라도 사람들이 사용하는 것이 좋습니다.
Porculus

11

줄 끝을 처리하는 나의 절차는 다음과 같습니다 (많은 repos에서 전투 테스트)

새로운 저장소를 만들 때 :

  • 넣어 .gitattributes에 매우 첫째, 다른 일반적인 같은 파일과 함께 커밋 .gitignoreREADME.md

기존 리포지토리를 처리 할 때 :

  • .gitattributes그에 따라 생성 / 수정
  • git commit -a -m "Modified gitattributes"
  • git rm --cached -r . && git reset --hard && git commit -a -m 'Normalize CRLF' -n"
    • -n( --no-verify미리 커밋 후크를 건너 뛰는 것입니다)
    • 별칭으로 정의하기에 충분할 정도로 자주 수행해야합니다. alias fixCRLF="..."
  • 이전 명령을 반복
    • 그렇습니다. 부두교이지만 일반적으로 명령을 두 번 실행해야합니다. 처음에는 일부 파일을 정규화 할 때, 두 번째로 더 많은 파일을 처리해야합니다. 일반적으로 새로운 커밋이 생성되지 않을 때까지 반복하는 것이 가장 좋습니다. :)
  • 이전 (정규화 직전)과 새 분기간에 몇 번 앞뒤로 이동합니다. 브랜치를 전환 한 후 때때로 git은 재 정규화해야하는 더 많은 파일을 찾을 수 있습니다!

에서 .gitattributes내가 LF EOL있는 것으로 명시 적으로 모든 텍스트 파일을 선언 하기 때문에 일반적으로 윈도우 도구는 Windows 이외의 도구가 CRLF와 호환되지 않습니다 동안 LF와 호환 (심지어 많은 nodejs이 줄 도구가 LF를 가정하고 따라서 파일의 EOL을 변경할 수 있습니다 명령).

내용 .gitattributes

.gitattributes보통은 다음과 같습니다

*.html eol=lf
*.js   eol=lf
*.json eol=lf
*.less eol=lf
*.md   eol=lf
*.svg  eol=lf
*.xml  eol=lf

현재 리포지토리에서 git이 추적하는 고유 한 확장을 확인하려면 여기를 참조하십시오.

정규화 후 문제

이 작업이 끝나면 일반적인 경고가 하나 더 있습니다.

귀하 master가 이미 최신 상태이고 정규화되었다고 확인한 다음 체크 아웃하십시오 outdated-branch. 그 지점을 체크 아웃 한 직후에 git은 많은 파일을 수정 된 것으로 표시합니다.

해결책은 가짜 커밋 ( git add -A . && git commit -m 'fake commit') 을 수행하는 것 git rebase master입니다. 리베이스가 끝나면 가짜 커밋이 사라집니다.


1
지정된 명령 시퀀스를 여러 번 실행해야하기 때문에 게시물을 읽을 때까지 미쳤다고 생각했습니다. 부두교! ;)
Sean Fausett

git version 2.7.0.windows.1에서는 다음을 사용했습니다. git rm --cached -r . && git reset --hard && git add . && git commit -m "Normalize EOL" -n
Sean Fausett

4
git status --short|grep "^ *M"|awk '{print $2}'|xargs fromdos

설명:

  • git status --short

    이것은 git이 알고 있고 모르는 각 줄을 표시합니다. git 제어가없는 파일은 줄의 시작 부분에 '?'로 표시됩니다. 수정 된 파일은 M으로 표시됩니다.

  • grep "^ *M"

    수정 된 파일 만 필터링합니다.

  • awk '{print $2}'

    마커가없는 파일 이름 만 표시합니다.

  • xargs fromdos

    이전 명령에서 파일 이름을 가져 와서 줄 끝을 변환하기 위해 'fromdos'유틸리티를 통해 파일 이름을 실행합니다.


대단해. 감사합니다. Homebrew를 사용 dos2unix하는 솔루션을 찾는 사람은 대신을 사용하십시오 fromdos.
Almir Sarajčić

4

다음을 사용하여 전체 기록에서 모든 줄 끝을 수정하는 방법은 다음과 같습니다 git filter-branch. ^M문자를 사용하여 입력 할 필요가 CTRL-V+를 CTRL-M. dos2unix바이너리 파일을 자동으로 건너 뛰기 때문에 파일을 변환하는 데 사용 했습니다.

$ git filter-branch --tree-filter 'grep -IUrl "^M" | xargs -I {} dos2unix "{}"'


3

"| xargs fromdos"는 표준 입력 (파일이 find찾은 것)을 읽어 명령의 인수 fromdos로 사용하여 줄 끝을 변환합니다. (그러한 환경의 표준은 있습니까? dos2unix에 익숙합니다). xargs 사용을 피할 수 있습니다 (특히 인수 목록이 xargs에 대해 너무 긴 파일이 충분한 경우에 유용합니다).

find <path, tests...> -exec fromdos '{}' \;

또는

find <path, tests...> | while read file; do fromdos $file; done

오류 메시지가 확실하지 않습니다. 이 방법을 성공적으로 테스트했습니다. 각각의 프로그램은 무엇입니까? 어떤 파일 / 디렉토리에 대한 권한이 없습니까? 그러나 여기에 무엇이 있는지 추측 할 수있는 방법이 있습니다.

스크립트에서 '파일을 찾을 수 없음'오류를 얻는 쉬운 방법 중 하나는 상대 경로를 사용하는 것입니다. 절대 경로를 사용하십시오. 마찬가지로 스크립트를 실행 가능하게하지 않으면 (chmod + x) 권한 오류가 발생할 수 있습니다.

의견을 추가하면 도움이 될 것입니다.


dos2unix의 또 다른 예를 보았고 이것이 어떻게 든 폴더에 파일을 복사하는 것이라고 생각했지만 지금은 그것을 얻습니다. 와우, 지금 분명해 보인다. 당신의 도움을 주셔서 감사합니다!
Brian Donahue

1

좋아 ... cygwin에서 우리는 쉽게 사용할 수있는 fromdo를 가지고 있지 않으며 수정 된 파일 (우리가 가진)의 경로에 공백이 있으면 awk substeb이 당신의 얼굴에 날아갑니다. 그래서 나는 약간 다르게해야했습니다.

git status --short | grep "^ *M" | sed 's/^ *M//' | xargs -n 1 dos2unix

이 솔루션의 대부분에 대한 @lloyd의 kudos


-2

다른 답변이 도움이되지 않으면 다음 단계를 따르십시오.

  1. Windows를 사용하는 경우 git config --global core.autocrlf true; 유닉스에 있다면git config core.autocrlf input
  2. 운영 git rm --cached -r .
  3. 파일 삭제 .gitattributes
  4. 운영 git add -A
  5. 운영 git reset --hard

그럼 당신의 지역은 지금 깨끗해야합니다.


4
정말? .gitattributes파일을 삭제 하면 줄 끝 문제가 해결됩니까?
Aleksandr M

예 @AleksandrM에 의해 코멘트를 해결하십시오
Mr_and_Mrs_D
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.