문서 작업 가이드
Git과 셸 스크립트에서 CRLF를 LF로 안전하게 변환하기
원본 줄바꿈 바이트를 진단하고 저장소 정책을 정한 뒤 인코딩 문제를 숨기지 않으면서 CRLF를 LF로 바꾸고 커밋 전에 스크립트와 diff를 검증합니다.
작성 및 검수 SimpleWebUtils게시일: 검토일:
이 작업 흐름을 검증한 방법
이번 검증은 “Windows에서 편집한 배포 스크립트 복구”의 정확한 입력과 CRLF, LF 및 혼합 텍스트 파일 줄바꿈 감지기를 짝지어 수행했습니다. “실패한 파일을 보존하고 원본 바이트 검사” 단계를 거쳐 “실행 환경과 저장소 정책에서 목표 형식 선택” 이후 결과를 캡처해 예시와 비교했습니다. 명시적인 경계 질문은 “감지 전에 파일을 textarea에 붙여넣기”, “CRLF는 제거했지만 shebang 앞 BOM을 남김”였습니다.
수정된 스크립트는 CRLF 3개를 LF로 바꾸고 최종 줄 종료 4개를 유지했으며, 명령문을 바꾸지 않고 shebang을 0번 바이트에서 다시 인식시켰습니다.
문제 상황
CRLF와 LF는 모두 유효한 줄바꿈 관례지만 둘 사이의 숨은 변경은 작은 수정을 파일 전체 Git diff로 만들거나 Linux shebang에 캐리지 리턴을 남길 수 있습니다. 파일이 바이너리이거나 UTF-16/32를 사용하거나 BOM이 있거나 의도적으로 CRLF로 체크아웃되는 경우 무작정 치환하면 위험합니다. 브라우저 textarea에 붙여넣으면 진단 전에 차이가 사라질 수 있고 core.autocrlf 때문에 작업 트리와 인덱스가 다를 수도 있습니다. 따라서 원본 바이트 근거, 별도의 인코딩·BOM 판단, 실제 소비 환경에서 정한 목표, 검토한 .gitattributes 정책, 대상 플랫폼의 변환 후 실행 확인이 함께 필요합니다.
이럴 때 사용하세요
- 다른 운영체제에서 조금 수정했는데 Git이 모든 줄을 변경으로 표시합니다.
- 셸 스크립트가 bad interpreter, command not found 또는 shebang 주변의 ^M 오류로 실패합니다.
- Docker 진입점, CI 스크립트, Makefile 조각 또는 환경 파일이 로컬에서는 동작하지만 Linux에서 실패합니다.
- CSV, 로그 또는 생성 텍스트 파일에 CRLF와 LF 레코드 종결자가 함께 있습니다.
- 저장소가 .gitattributes를 도입하며 정규화 전후를 측정해야 합니다.
단계
- 1단계
실패한 파일을 보존하고 원본 바이트 검사
손대지 않은 복사본이나 실제 실패한 Git 리비전을 유지하세요. textarea 값은 줄바꿈을 LF로 정규화하므로 붙여넣지 말고 줄바꿈 감지기에서 파일 자체를 검사합니다. CRLF, LF, CR, 전환 줄, 마지막 종결자를 기록하세요.
- 2단계
텍스트 입력인지 확인하고 인코딩 검토
바이너리 데이터가 의심되면 중단하세요. UTF-16/32는 BOM을 확인하거나 감지기의 휴리스틱 경고를 검토합니다. 첫 줄에 BOM이 있으면 BOM 제거와 줄바꿈 변환을 서로 다른 결정으로 다루세요.
- 3단계
실행 환경과 저장소 정책에서 목표 형식 선택
셸 스크립트, Docker 진입점, 대부분의 교차 플랫폼 소스 저장소에는 LF를 사용합니다. Windows 전용 소비자가 명시적으로 요구할 때만 CRLF를 유지하세요. 결정 전에 .gitattributes, core.autocrlf, 편집기 설정을 함께 확인합니다.
- 4단계
확인된 텍스트를 한 번에 통일
텍스트 정리 워크벤치의 줄바꿈 작업으로 파일 전체를 LF로 변환합니다. UTF-16/32나 텍스트로 확인되지 않은 파일에 원시 바이트 치환을 실행하지 마세요.
- 5단계
첫 줄과 마지막 줄바꿈을 별도로 확인
실행 스크립트는 shebang이 0번 바이트에서 시작하고 앞에 BOM이 없는지 확인합니다. 프로젝트가 마지막 LF를 요구하는지 확인한 뒤 변환이 자동으로 만들었다고 가정하지 말고 의도적으로 추가하세요.
- 6단계
다시 감지하고 Git diff 검토
후속 보고서는 LF만 표시하고 예상하지 않은 Unicode 구분자가 없으며 의도한 마지막 종결자를 보여야 합니다. git diff --ignore-space-at-eol은 진단 비교에만 쓰고 커밋 전에 일반 diff를 확인하세요.
- 7단계
정책을 고정하고 실제 대상에서 실행
적절하다면 *.sh text eol=lf 같은 범위가 명확한 .gitattributes 규칙을 추가하고 편집기 설정을 맞춘 뒤 대상 플랫폼에서 스크립트나 CI 작업을 실행합니다. 계획하고 검토한 작업이 아니라면 같은 커밋에서 저장소 전체를 정규화하지 마세요.
예시
Windows에서 편집한 배포 스크립트 복구
입력
원본 선두 바이트: 23 21 2F 62 69 6E 2F 62 61 73 68 0D 0A
감지 결과: CRLF 3, LF 1, 첫 혼합 줄 3
Linux: /bin/bash^M: bad interpreter출력
결정: 저장소 정책상 *.sh는 LF 사용
변환 후: CRLF 0, LF 4, 마지막 종결자 LF
검증: shebang이 0번 바이트에서 시작하고 일반 Git diff를 확인했으며 Linux CI에서 실행됨흔한 실수
감지 전에 파일을 textarea에 붙여넣기
브라우저가 textarea API 값의 CRLF와 CR을 LF로 정규화해 확인하려던 근거를 없앨 수 있습니다. 원본 파일을 선택하세요.
알 수 없는 인코딩에 바이트 치환 실행
UTF-16과 UTF-32는 CR과 LF를 여러 바이트 코드 단위로 표현합니다. 인코딩을 확인하고 떨어진 0D 또는 0A 바이트를 치환하지 말고 텍스트 인식 변환 경로를 사용하세요.
CRLF는 제거했지만 shebang 앞 BOM을 남김
UTF-8 BOM 바이트가 #! 앞에 남으면 스크립트가 계속 실패할 수 있습니다. 줄바꿈 변환 후 0번 바이트를 별도로 확인하세요.
core.autocrlf 전역 변경만으로 해결
개발자 전역 설정은 저장소 의도를 숨기고 컴퓨터마다 다르게 동작할 수 있습니다. 프로젝트 정책에는 검토한 .gitattributes 규칙을 우선하세요.
코드 수정과 저장소 전체 정규화를 한 번에 수행
거대한 기계적 diff는 실제 수정을 숨기고 되돌리기를 어렵게 합니다. 계획한 정규화는 분리하고 대상 빌드나 실행 환경에서 검증하세요.
자주 묻는 질문
모든 Git 저장소가 LF를 저장해야 하나요?
대부분의 교차 플랫폼 소스 저장소는 인덱스에 LF를 쓰지만 생성 파일과 Windows 전용 소비자는 다른 요구가 있을 수 있습니다. 선택한 규칙을 .gitattributes에 명시하세요.
/bin/bash^M은 왜 나타나나요?
CRLF의 CR이 shebang 인터프리터 경로 뒤에 남아 Linux가 캐리지 리턴까지 포함한 경로의 인터프리터를 찾게 되기 때문입니다.
git diff --ignore-space-at-eol이 파일을 고치나요?
아니요. 비교 표시 방식만 바꿉니다. 의도한 텍스트를 통일하고 일반 diff를 검토한 뒤 결과 파일을 테스트하세요.
UTF-16 파일도 UTF-8과 같은 방법으로 통일해도 되나요?
의도한 UTF-16 바이트 순서와 BOM 정책을 보존하는 디코더와 인코더를 사용해야 합니다. UTF-8 파일처럼 개별 줄바꿈 바이트를 치환하지 마세요.
텍스트 파일은 반드시 줄바꿈으로 끝나야 하나요?
많은 소스 및 POSIX 중심 작업 흐름은 마지막 줄바꿈을 기대하지만 모든 데이터 형식이 요구하지는 않습니다. 저장소와 소비자 계약을 확인한 뒤 감지기의 마지막 종결 결과로 검증하세요.
core.autocrlf는 언제 사용해야 하나요?
저장소 정책의 대체물이 아닌 작업 컴퓨터의 체크아웃 선호로 다루세요. .gitattributes가 공동 작업자에게 공유되는 경로별 규칙을 제공합니다.