2016-12-14 8 views
5

우리는 혼합 환경에서 개발합니다 - 일부 사람들은 Mac에서 작업하고 일부는 Linux에서 작업합니다. Linux에서 작업하는 사람들은 파일 시스템이 대소 문자를 구분하는 데 익숙하므로 시간이 지남에 따라 여러 파일을 (실수로 또는 다른 방식으로) 커밋하는 데 아무런 문제가 없습니다. 경우에만 다른 - - 서로 덮어 및 일반 혼란의 원인 (예를 들어, FileName.extfilename.ext 대)git이 대소 문자 만 다른 두 개의 파일을 커밋하지 않도록하려면 어떻게해야합니까?

그러나

, 맥에있는 사람들이 대소 문자를 구분 파일 시스템을 가지고, 저장소를 체크 아웃로 이동이 개 파일이 있다는 것을 의미한다.

내가 거기 대소 문자 구분 파일 시스템에 사람들을 돕기 위해 다양한 자식 설정은 경우 변경 (예 : core.ignorecase를) 더 잘 작동하는지 알고 있지만, 이들은 저장소에 두 개의 서로 다른 파일을 거기에 문제 만하여 다른 해결되지 않습니다 케이스.

나는 그것을 고치기위한 유일한 방법은 리눅스 사람들이 첫 번째 경우에만 다른 두 파일을 커밋하지 않도록하는 것임을 알고 있습니다. - git에서 대소 문자를 구별하는 파일 시스템의 사용자가 대소 문자를 구별하지 않는 파일 시스템에서 서로 혼동을 일으킬만한 파일을 커밋하려고 시도하면 경고 또는 오류가 나타납니다.

+0

참고 [이 유닉스 및 리눅스 SE 포스트 (http://unix.stackexchange.com/questions/85410/how-to-find-file-directory-names-that-are-the-same- but-with-different-capitaliz)에는 대부분의 리눅스 용 디렉토리에서 이러한 파일을 찾을 수있는 접근법이 있지만 git에 연결되지는 않습니다. (따라서 파일이 커밋되기 전에 실행되지 않고 커밋 된 파일에만 국한되지 않습니다.) –

답변

4

아무 것도 내장되어 있지 않습니다 (의심의 여지가 있지만). 당신이 할 수있는 일은 모든 이름들이 OK인지 아닌지를 확인하고 그렇지 않다면 커밋을 막는 pre-commit hook을 제공하는 것입니다.

이 훅은 리눅스 박스에서만 실행하면됩니다. (리눅스와 맥에서 작동하게하는 것은 쉽지만 문제가되는 기본 빈곤 한 툴박스가있는 윈도우 일뿐입니다). 사이드 브랜치에 추가하고 리눅스 사용자에게 설정에 대한 지침을 제공 할 수 있습니다.

브랜치를 확인할 수도 있습니다 (git pre-commit or update hook for stopping commit with branch names having Case Insensitive match). (흥미 롭습니다 :이 질문에 대한 답은 제 자신의 것이므로 잊어 버렸습니다.)

먼저 "사례 충돌 확인"기능을 작성해 보겠습니다. 이것은 대소 문자 접기 ("helloworld"와 "helloWorld"가 서로 인접하여 배치되도록)를 정렬 한 다음 uniq -di을 사용하여 중복 된 (대/소문자 접미어 이후) 문자열은 인쇄하지만 중복이 아닌 것은 인쇄 할 수 없습니다.

sort -f | uniq -di 

출력 결과가 "나쁜 이름"인 경우 의 임시 파일에 출력을 캡처하고 그 크기를 확인하자, 그래서 우리는뿐만 아니라 표준 출력을 인쇄 할 수 있습니다

#! /bin/sh 

TF=$(mktemp) 
trap "rm -f $TF" 0 1 2 3 15 
checkstdin() { 
    sort -f | uniq -di > $TF 
    test -s $TF || return 0 # if $TF is empty, we are good 
    echo "non-unique (after case folding) names found!" 1>&2 
    cat $TF 1>&2 
    return 1 
} 

지금 우리가 최선을 다하고됩니다 파일을 사용해야하고, 아마도 지점 이름에 게다가. 전자는, 그래서 git ls-files로 나열되어 있습니다 :이 최대가 git diff-index --cached -r --name-only --diff-filter=A HEAD를 사용하는

당신이 할 수있는
git ls-files | checkstdin || { 
    echo "ERROR - file name collision, stopping commit" 1>&2 
    exit 1 
} 

공상 만 기존의 경우 충돌을 계속 할 수 있도록 파일을 추가 확인 및/또는 많은 지점을 통해 물건을 확인하기 위해 노력하고/또는 커밋하지만 어렵습니다.

위의 두 조각을 하나의 스크립트 (및 테스트)로 결합한 다음 .git/hooks/pre-commit이라는 실행 파일에 복사하기 만하면됩니다.

분기 이름을 확인하는 것이 약간 번잡합니다.실제로 커밋 할 때가 아닌 지점 이름을 만들 때 클라이언트에서 실제로 작업을 수행하는 것은 불가능합니다. 적절한 글로벌보기가있는 중앙 집중식 서버에서 수행해야합니다.

사전 수신 스크립트에서 파이썬이 아닌 쉘 스크립트 (링크 된 응답과 같이)에서 서버에서 수행하는 방법입니다. 그래도 checkstdin 함수가 필요하며 전체 푸시 (단지 하나의 브랜치 이름)를 거부 할 필요가 없으므로 사전 수신 후크가 아닌 업데이트 훅에서 수행해야 할 수 있습니다.

NULLSHA=0000000000000000000000000000000000000000 # 40 0s 

# Verify that the given branch name $1 is unique, 
# even IF we fold all existing branch names' cases. 
# To be used on any proposed branch creation (we won't 
# look at existing branches). 
check_new_branch_name() { 
    (echo "$1"; git for-each-ref --format='%(refname:short)' refs/heads) | 
     checkstdin || { 
     echo "ERROR: new branch name $1 is not unique after case-folding" 1>&2 
     exit 1 # or set overall failure status 
    } 
} 

while read oldsha newsha refname; do 
    ... any other checks ... 
    case $oldsha,$refname in 
    $NULLSHA,refs/heads/*) check_new_branch_name ${refname#refs/heads/};; 
    esac 
    ... continue with any other checks ... 
done 
+0

시스템 별 파일 이름 규칙의 모든 순열에 대한 논리가 포함되므로이 문제는 계속 처리해야한다는 것에 동의하지 마십시오 . 어쨌든 품질 응답에 대한지지를받습니다. –

+0

@JoeAtzberger : 여기에 끝없는 문제 행렬이 있다는 것은 사실입니다. 하지만 우리는 일반적인 "파일 이름 맵"솔루션 (Git 자체에서)과 간단한 충돌 감지 및 조작 (Git 지원 타사 소스 코드, 일종의 메일 수신 후 스크립트가 진화 한 방식). 내가 "파일 이름 맵"에 대해 생각하는 것은'.gitattributes' 또는'.git/info/exclude'와 같은 것입니다. 아마도'.git/info'에 저장되어 있습니다. 와이". 제 3 자 코드가 맵을 빌드하고'checkout'이 맵을 사용합니다. – torek

+0

약간 더 자세하게 설명하자면,지도는 실제로 깨끗하고 얼룩이 진 필터와 줄 끝 (CR/LF) 변환 필터가 수행되는 것과 같은 방법으로 색인 밖으로 또는 밖으로 파일 전환에 실제로 적용됩니다. 이렇게하면 Windows 또는 Mac 사용자가 실제로 액세스 할 수없는 이름의 파일을 추출, 수정 및 커밋 할 수 있습니다. 실용적이지 않는 한 장기간의 일반적인 사용을위한 것이 아닙니다. – torek