git-merge가 줄 끝 차이점을 무시할 수 있습니까?


150

git merge줄 끝의 차이점을 무시할 수 있습니까?

어쩌면 나는 잘못된 질문을하고 있습니다 ...하지만 :

나는 uisng을 시도 config.crlf input했지만 특히 사실 이후에 적용했을 때 상황이 약간 지저분하고 통제 불능 상태가 되었습니다 .

사실, 사실 이후에이 설정을 적용해도이 옵션을 적용하기 전에 리포지토리에 커밋 된 파일에는 영향을 미치지 않는 것 같습니다. 또 다른 것은 갑자기 모든 커밋이 CRLF가 LF로 변환되는 것에 대한 많은 성가신 경고 메시지를 초래한다는 것입니다.

솔직히 말해서 어떤 줄 끝이 사용되는지는 신경 쓰지 않고 개인적으로 유닉스 스타일을 선호 \n하지만 무엇이든간에 선호합니다 . 내가 걱정 git merge하는 것은 조금 더 똑똑하고 줄 끝의 차이점을 무시하는 것입니다.

때로는 두 개의 동일한 파일이 있지만 git은 단순히 다른 줄 끝 문자를 사용하기 때문에 충돌하는 것으로 표시합니다 (그리고 충돌은 전체 파일입니다).

최신 정보:

옵션 을 git diff허용 한다는 것을 알았습니다. 이 옵션도 사용할 --ignore-space-at-eolgit merge있습니까?


28
오 바란다. git의이 줄 끝은 완전히 깨졌습니다.
1800 INFORMATION

해당 써드 파티 병합 도구가 병합 중에 eol 스타일을 무시한다는 것을 보여주는 테스트 사례를 추가했습니다
VonC

따라서, (내가 결정할 수있는 것에서) 명확하게하기 위해 : git이 CR을 무시하도록 할 수는 없지만 다른 모든 공백에 대해 불평 할 수 있습니까?
Stephen

git config merge.renormalize true
qneill에

답변:


115

2013 년 업데이트 :

최신 git 버전은 전략 recursive및 전략 옵션 ( -X) 과 병합을 사용하여 권한을 부여합니다 .

git merge -s 재귀 -Xignore-space-at-eol

하지만 " -Xignore-space-change"를 사용 하는 것도 가능합니다


jakub.g 또한 코멘트 한다는 전략 체리 따기와도 작동 :

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

이보다 훨씬 잘 작동합니다 ignore-all-space.


원래 답변 (2009 년 5 월)

eol 스타일을 무시하기위한 패치는 2007 년 6 월 에 제안 되었지만 git diff --ignore-space-at-eol, 그다지 중요 하지는 않습니다 git merge.

당시 질문이 제기되었습니다.

해야 --ignore-space-at-eol하는 옵션이 될 git-merge?
병합은이 기능이 중요한 부분입니다.
자동 해결 병합의 의미는 실제로 해당 옵션과 함께 적용됩니다. 이름 바꾸기 감지에만 사용됩니까, 아니면 공백 변경만으로 플래그 충돌이 발생하지 않습니까? 그렇지 않으면 어떤 버전을 자동으로 수락합니까?

Julio C Hamano는 정확히 열광적이지 않았습니다.

확실히 유혹적이지만, 나중의 라운드로 가야한다고 생각합니다.
나는 그것이 두 가지 다른 종류의 diff의 개념을 도입 할 것으로 의심합니다. 하나는 기계적으로 처리되어야합니다 (즉, "git-merge-recursive"와 병합하여 사용하고 "git-am"으로 적용). 인간은 이해합니다.
Munged 입력 파일을 비교 한 결과를 기계 적용에 쉽게 사용할 수는 없지만 후자의 경우 입력을 조정하는 것이 종종 유용 할 수 있습니다.

일반적인 아이디어 git merge는 타사 병합 도구를 사용하는 것입니다.

예를 들어, DiffMerge 를 Git 병합을위한 도구로 설정하고 해당 병합 도구가 특정 유형의 파일에 대한 eol을 무시하도록 규칙 세트 를 설정했습니다 .


DysMerge 또는 KDiff3을 사용하여 DOS 또는 Git bash 세션에 대해 MSysGit1.6.3을 사용하여 Windows에서 설정 :

  • 디렉토리를 PATH에 설정하십시오 (여기 :) c:\HOMEWARE\cmd.
  • 해당 디렉토리에 스크립트 merge.sh (좋아하는 병합 도구의 래퍼)를 추가하십시오.

merge.sh :

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
  • Git 용 병합 래퍼 선언

힘내 설정 명령 :

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh \"$PWD/$LOCAL\" \"$PWD/$BASE\" \"$PWD/$REMOTE\" \"$PWD/$MERGED\"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
  • autoCRLF가 false인지 확인하십시오.

시스템 레벨에서의 git config :

git config ---system core.autoCRLF=false
  • 두 줄이 동일하지만 eol 문자 인 경우 DiffMerge 또는 KDiff3은 병합 중에 해당 줄을 무시합니다.

DOS 스크립트 (참고 : dos2unix 명령은 here 이며 Unix eol 스타일을 시뮬레이션하는 데 사용됩니다.이 명령은이 답변의 시작 부분에 언급 된 디렉토리에 복사되었습니다.) :

C:\HOMEWARE\git\test>mkdir test_merge C:\HOMEWARE\git\test>cd test_merge C:\HOMEWARE\git\test\test_merge>git init C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout -b windows Switched to a new branch 'windows' C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout master C:\HOMEWARE\git\test\test_merge>git checkout -b unix Switched to a new branch 'unix' C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:\HOMEWARE\git\test\test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:\HOMEWARE\git\test\test_merge>git merge windows Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. C:\HOMEWARE\git\test\test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:\HOMEWARE\git\test\test_merge>git mergetool Merging the files: a.txt Normal merge conflict for 'a.txt': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):

이 시점에서 ( "반환"을 누르면) DiffMerge 또는 KDiff3이 열리고 실제로 병합 된 행과 무시되는 행을 직접 확인할 수 있습니다.

경고 : 결과 파일은 항상 DiffMerge와 함께 Windows eol 모드 (CRLF)에있게됩니다 ...
KDiff3는 한 가지 방법으로 저장하도록 제안합니다.


팁 주셔서 감사합니다! Mac의 Meld 및 FileMerge도 훌륭한 앱인 것 같습니다.
Léo Léopold Hertz 준영

1
정보의 경우, 전략과도 작동 체리 따기 : git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize (이 훨씬 더 이상 작동 ignore-all-space)
jakub.g

1
@ jakub.g 좋은 지적! 더 많은 가시성을 위해 답변에 포함 시켰습니다.
VonC

98

나는 같은 대답을 찾고 있었고, 난 발견

체크인 / 체크 아웃 속성이 다른 브랜치 병합

정리 / 스머지 필터 또는 텍스트 / Eol / ident 속성 추가와 같이 해당 파일의 표준 저장소 형식을 변경하는 속성을 파일에 추가 한 경우 속성이없는 위치를 병합하면 일반적으로 병합 충돌이 발생합니다 .

이러한 불필요한 병합 충돌을 방지하기 위해 git은 merge.renormalize 구성 변수를 설정하여 3 방향 병합을 해결할 때 파일의 세 단계 모두에서 가상 체크 아웃 및 체크인을 실행하도록 지시 할 수 있습니다. 이렇게하면 변환 된 파일을 변환되지 않은 파일과 병합 할 때 체크인 변환으로 인한 변경으로 인해 가짜 병합 충돌이 발생하지 않습니다.

이미 번져있는 파일에서도 "스머지 → 청소"결과가 "청소"와 동일한 결과를 얻는 한이 전략은 모든 필터 관련 충돌을 자동으로 해결합니다. 이러한 방식으로 작동하지 않는 필터는 수동으로 해결해야하는 추가 병합 충돌이 발생할 수 있습니다.

따라서 모든 저장소 에서이 명령을 실행하면 트릭이 수행됩니다.

git config merge.renormalize true

20
이것은 이제 기본 답이 될 자격이 있습니다. 질문이 처음 제기 된 이후로 많은 변화가 있었으며, git의 처리는 이제 merge.renormalize로 내장되어 있습니다.
Anton I. Sipos

이 .. 단지 굉장 내 일 저장
matthaeus



4

내가 한 것은 모든 것을 기본값으로 유지하고 (예 : autocrlf = true) 모든 파일을 만지십시오 (find. -exec touch {} \;). git이 파일을 '수정 됨'으로보고 다시 커밋 한 다음 완료하십시오. 그렇지 않으면 항상 성가신 메시지 또는 놀라운 차이점에 시달리고 git의 공백 기능을 모두 해제해야합니다.

당신은 비난 정보를 잃을 것이지만 나중에보다는 빨리하는 것이 좋습니다. :)





0

이제 가장 좋은 방법은 병합하기 전에 두 분기의 줄 끝을 정규화하고 커밋하는 것입니다.

나는 "crlf를 lf로 변환"을 봤는데 이것을 첫 번째 결과로 찾았습니다
.

나는 그것을 다운로드하여 사용했는데 멋진 도구 인 것 같습니다.

>sfk remcr . .py

디렉토리와 파일 형식 (예 : .py)을 지정해야합니다. 그렇지 않으면 .git디렉토리 의 내용을 망칠 수 있습니다 !


0

AFAICT, (시도하지 않았습니다) 당신은 git diff공통 조상과 병합하려는 지점을 비교하고로 결과를 적용하는 데 사용할 수 있습니다 git apply. 두 명령 모두 --ignore-whitespace줄 끝 및 공백 오류를 무시하는 옵션 이 있습니다.

안타깝게도 패치가 깨끗하게 적용되지 않으면 전체 작업이 중단됩니다. 병합 충돌을 해결할 수 없습니다. --reject패치 불가능한 .rej파일을 파일 에 남겨 두는 옵션 이 있는데 , 이는 하나의 파일에 병합 충돌이 나타나는 것과 동일하지 않습니다.


-1

병합 충돌 해결을 읽은 후 : 모든 파일을 강제로 덮어 씁니다.

마침내이 문제의 내 버전을 해결했습니다. 업스트림 리포지토리에서 업데이트를 가져 오려고했지만 현재 CRLF 관련 문제가 발생하여 병합 할 수 없었습니다. 내가 걱정해야 할 로컬 변경 사항이 없었습니다. 다음 단계로 문제가 해결되었습니다.

포크 동기화에 대한 github의 지침에 따라 ( https://help.github.com/articles/syncing-a-fork/ ) :

  1. git fetch upstream

  2. git reset --hard upstream/master
    git에 대한 나의 제한된 이해는 이것이 내가 원하는 것을하고 있음을 말해줍니다. (실제 커밋되지 않은 변경 사항없이) 포크를 재배치하여 업스트림 소스의 모든 변경 사항을 얻습니다. 소스 페이지에 따르면이 단계는 일반적으로 필요하지 않지만 CRLF 문제로 인해 필요했습니다.

  3. git merge upstream/master

  4. git push

1
당신은 git reset --hard upstream/master당신의 지역 지점을 버리고 그것을 가리키고 , no-op를 upstream/master만드는 git merge upstream/master것을 알고 있습니까?
Christoffer Hammarström

-1

그러나 올바른 줄 끝을 달성하고 파일을 비교하기 위해 sed와 같은 도구를 사용하는 것이 좋습니다. 나는 다양한 라인 엔딩으로 프로젝트 를 나누는 데 몇 시간을 보냈습니다 .

가장 좋은 방법은 다음과 같습니다.

  1. 프로젝트 파일 ( .git디렉토리 생략 ) 만 다른 디렉토리에 복사 하여 저장소를 작성한 후 파일을 추가하고 커미트하십시오 (새 저장소의 마스터 브랜치에 있어야 함).
  2. 두 번째 프로젝트에서 같은 폴더로 파일을 복사하지만 다른 분기 dev( 예 git checkout -b dev:),이 분기에서 파일을 커밋하고 실행하십시오 (첫 번째 프로젝트가 마스터에있는 경우) : git diff master..dev --names-only 변경된 파일의 이름 만 보려면
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.