팀과 함께 git을 사용하고 있으며 diff, log, merge 등에서 공백 변경 사항을 제거하고 싶습니다.이 작업을 수행하는 가장 쉬운 방법은 git이 후행 공백 (및 기타 공백 오류)을 자동으로 제거하는 것이라고 가정합니다 ) 적용되는 모든 커밋에서.
~/.gitconfig
파일로 다음을 추가하려고했지만 커밋 할 때 아무것도하지 않습니다. 어쩌면 다른 무언가를 위해 설계되었을 수도 있습니다. 해결책은 무엇입니까?
[core]
whitespace = trailing-space,space-before-tab
[apply]
whitespace = fix
누구든지 루비 관련 아이디어가있는 경우를 대비하여 루비를 사용하고 있습니다. 커밋하기 전에 자동 코드 형식화는 다음 단계이지만, 어려운 문제이며 실제로 큰 문제를 일으키지 않습니다.
답변
이러한 설정 ( core.whitespace
및 apply.whitespace
)은 후행 공백을 제거하지 않고 다음을 수행합니다.
core.whitespace
: 감지하여 오류 발생apply.whitespace
: 항상 “자동으로”가 아닌 패치 중에 만 제거하십시오.
나는 그것을 위해 git hook pre-commit
더 나은 일을 할 것이라고 믿는다 (후행 공백 제거 포함)
주어진 시간에 pre-commit
후크를 실행하지 않도록 선택할 수 있습니다 .
- 일시적으로 :
git commit --no-verify .
- 영구적으로 :
cd .git/hooks/ ; chmod -x pre-commit
경고 : 기본, a로 pre-commit
(같은 스크립트 이 하나 ), 한 없는 기능 “을 후행 제거” “하지만,”경고 “기능과 같은 :
if (/\s$/) {
bad_line("trailing whitespace", $_);
}
그러나 특히 다음을 고려할 때 더 나은 pre-commit
후크를 만들 수 있습니다.
준비 영역에 약간의 변경 사항 만 추가하여 Git에서 커밋하면 여전히 작업 복사본으로 존재하지 않았거나 작동하지 않을 수 있는 “원자”개정이 생성 됩니다.
예를 들어, 노인 은 다른 대답 에서 공백을 감지하고 제거 하는 pre-commit
후크 를 제안합니다 .
그 후크는 각 파일의 파일 이름을 얻으므로 특정 유형의 파일에주의를 기울이는 것이 좋습니다. .md
(마크 다운) 파일 에서 후행 공백을 제거하고 싶지 않습니다 !
답변
변경 사항을 패치로 처리하도록 Git을 속여서 Git이 공백을 수정하도록 속일 수 있습니다. “사전 커밋 후크”솔루션과 달리이 솔루션은 Git에 공백 수정 명령을 추가합니다.
예, 이것은 해킹입니다.
강력한 솔루션
다음 Git 별칭은 my~/.gitconfig
에서 가져옵니다
.
“견고한”이란 트리 나 인덱스가 더티인지에 관계없이 이러한 별칭이 오류없이 실행되고 올바른 작업을 수행함을 의미합니다. 그러나 대화식 git rebase -i
이 이미 진행중인 경우 작동하지 않습니다 . 마지막에 설명 된 트릭이 작동하는 이 코너 케이스에 관심이 있다면 추가 확인을 위해 내~/.gitconfig
참조하십시오 git add -e
.
Git 별칭을 만들지 않고 쉘에서 직접 실행하려면 큰 따옴표 사이에 모든 것을 복사하여 붙여 넣으십시오 (쉘이 Bash와 같다고 가정).
색인을 수정하지만 트리는 수정하지 마십시오
다음 fixws
Git 별칭은 인덱스의 모든 공백 오류를 수정하지만 트리를 건드리지 않습니다.
# Logic:
#
# The 'git stash save' fails if the tree is clean (instead of
# creating an empty stash :P). So, we only 'stash' and 'pop' if
# the tree is dirty.
#
# The 'git rebase --whitespace=fix HEAD~' throws away the commit
# if it's empty, and adding '--keep-empty' prevents the whitespace
# from being fixed. So, we first check that the index is dirty.
#
# Also:
# - '(! git diff-index --quiet --cached HEAD)' is true (zero) if
# the index is dirty
# - '(! git diff-files --quiet .)' is true if the tree is dirty
#
# The 'rebase --whitespace=fix' trick is from here:
# https://stackoverflow.com/a/19156679/470844
fixws = !"\
if (! git diff-files --quiet .) && \
(! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git stash save FIXWS_SAVE_TREE && \
git rebase --whitespace=fix HEAD~ && \
git stash pop && \
git reset --soft HEAD~ ; \
elif (! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git rebase --whitespace=fix HEAD~ && \
git reset --soft HEAD~ ; \
fi"
아이디어는 색인에 공백 오류가있는 경우 git fixws
전에 실행하는 것입니다 git commit
.
인덱스와 트리를 수정
다음 fixws-global-tree-and-index
Git 별명은 색인 및 트리의 모든 공백 오류를 수정합니다 (있는 경우).
# The different cases are:
# - dirty tree and dirty index
# - dirty tree and clean index
# - clean tree and dirty index
#
# We have to consider separate cases because the 'git rebase
# --whitespace=fix' is not compatible with empty commits (adding
# '--keep-empty' makes Git not fix the whitespace :P).
fixws-global-tree-and-index = !"\
if (! git diff-files --quiet .) && \
(! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git add -u :/ && \
git commit -m FIXWS_SAVE_TREE && \
git rebase --whitespace=fix HEAD~2 && \
git reset HEAD~ && \
git reset --soft HEAD~ ; \
elif (! git diff-files --quiet .) ; then \
git add -u :/ && \
git commit -m FIXWS_SAVE_TREE && \
git rebase --whitespace=fix HEAD~ && \
git reset HEAD~ ; \
elif (! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git rebase --whitespace=fix HEAD~ && \
git reset --soft HEAD~ ; \
fi"
버전이 지정되지 않은 파일에서 공백을 수정하려면
git add --intent-to-add <unversioned files> && git fixws-global-tree-and-index
단순하지만 강력한 솔루션
이러한 버전은 복사 및 붙여 넣기가 더 쉬워 지지만 해당 조건이 충족되지 않으면 올바른 작업을 수행하지 않습니다.
현재 디렉토리를 기반으로하는 하위 트리 수정 (비어 있지 않은 경우 인덱스 재설정)
git add -e
아이디 편집기로 패치를 “편집”하는 데 사용 :
:
(export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .) && git checkout . && git reset
색인 수정 및 보존 (트리가 더럽거나 색인이 비어있는 경우 실패)
git commit -m TEMP && git rebase --whitespace=fix HEAD~ && git reset --soft HEAD~
나무와 색인을 수정하십시오 (그러나 비어 있지 않으면 색인을 재설정하십시오)
git add -u :/ && git commit -m TEMP && git rebase --whitespace=fix HEAD~ && git reset HEAD~
export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .
트릭의 설명
이 답변 에서 git rebase --whitespace=fix
트릭 에 대해 배우기 전에 더 복잡한 트릭을 사용했습니다 .git add
우리가 수동으로 한 경우 :
-
설정
apply.whitespace
에fix
(당신은 한 번만 수행하면) :git config apply.whitespace fix
이것은 Git에게 패치 에서 공백을 수정하도록 지시 합니다.
-
Git이 변경 사항을 패치 로 취급하도록 설득 하십시오 .
git add -up .
각 파일에 대한 모든 변경 사항을 선택하려면 a+ enter를 누르십시오 . Git의 공백 오류 수정에 대한 경고가 표시됩니다.
(git -c color.ui=auto diff
이 시점에서 색인이 생성되지 않은 변경 사항은 정확히 공백 오류임을 나타냅니다). -
작업 사본에서 공백 오류를 제거하십시오.
git checkout .
-
변경 사항을 다시 가져 오십시오 (커밋 할 준비가되지 않은 경우).
git reset
편집기 및 명령
GIT_EDITOR=:
으로 사용 하는 수단 은 ID입니다.:
:
답변
후행 공백을 제거 하는 자식 사전 커밋 후크를 찾았습니다 .
#!/bin/sh
if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -r 's/:[0-9]+:.*//' | uniq` ; do
# Fix them!
sed -i 's/[[:space:]]*$//' "$FILE"
git add "$FILE"
done
exit
답변
Mac OS (또는 BSD)에서 sed 명령 매개 변수는 약간 달라야합니다. 이 시도:
#!/bin/sh
if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -E 's/:[0-9]+:.*//' | uniq` ; do
# Fix them!
sed -i '' -E 's/[[:space:]]*$//' "$FILE"
git add "$FILE"
done
이 파일을 다른 이름으로 저장 .git/hooks/pre-commit
하거나 이미 존재하는 파일을 찾아서 그 안에 어딘가에 하단 청크를 붙여 넣습니다. 그리고 chmod a+x
그것도 기억하십시오 .
또는 글로벌 사용 (경유 – 전역 설정 힘내 후크를 저지 당신이 그것을 넣을 수 있습니다) $GIT_PREFIX/git-core/templates/hooks
(GIT_PREFIX에 / usr 또는 경우 / usr / local이나 / usr / 주 또는 / 옵션 / 지역 / 공유) 실행 git init
기존의 repos 내부.
에 따르면 git help init
:
기존 저장소에서 git init를 실행하는 것이 안전합니다. 이미 존재하는 것을 덮어 쓰지 않습니다. git init를 다시 실행하는 주된 이유는 새로 추가 된 템플릿을 선택하는 것입니다.
답변
차라리이 작업을 좋아하는 편집자에게 맡기고 싶습니다.
저장할 때 후행 공백을 제거하도록 명령을 설정하십시오.
답변
자식 속성 사용 및 자식 설정으로 필터 설정
좋아, 이것은이 문제를 해결하기위한 새로운 방법입니다 … 내 접근 방식은 후크를 사용하지 않고 필터와 자식 속성을 사용하는 것입니다. 이 기능을 사용하면 개발중인 각 컴퓨터에서 파일 끝에 커밋하기 전에 추가 공백과 줄을 제거하는 필터 세트가 설정됩니다. 그런 다음 필터를 적용 할 파일 형식을 나타내는 .gitattributes 파일을 설정하십시오. 필터에는 clean
파일을 색인에 추가 할 때 적용되는 단계 와 smudge
작업 디렉토리에 추가 할 때 적용되는 두 단계 가 있습니다.
자식에게 전역 속성 파일을 찾도록 지시하십시오.
먼저 전역 속성 파일을 사용하도록 전역 구성에 지시하십시오.
git config --global core.attributesfile ~/.gitattributes_global
글로벌 필터 만들기
이제 필터를 작성하십시오.
git config --global filter.fix-eol-eof.clean fixup-eol-eof %f
git config --global filter.fix-eol-eof.smudge cat
git config --global filter.fix-eol-eof.required true
sed 스크립팅 매직 추가
마지막으로, fixup-eol-eof
스크립트를 경로 어딘가에 놓고 실행 가능하게 만드십시오. 스크립트는 sed를 사용하여 일부 편집 작업을 수행합니다 (파일 끝에서 공백과 공백을 제거하고 파일 끝에서 불필요한 공백을 제거합니다)
fixup-eol-eof는 다음과 같아야합니다.
#!/bin/bash
sed -e 's/[ ]*$//' -e :a -e '/^\n*$/{$d;N;ba' -e '}' $1
git에게 새로 만든 필터를 적용 할 파일 형식을 알려주세요
마지막으로 좋아하는 편집기에서 ~ / .gitattributes_global을 만들거나 열고 다음과 같은 줄을 추가하십시오.
pattern attr1 [attr2 [attr3 […]]]
따라서 공백 문제를 해결하려면 모든 c 소스 파일에 대해 다음과 같은 줄을 추가하십시오.
*.c filter=fix-eol-eof
필터에 대한 토론
필터에는 두 가지 단계가 있습니다. 색인에 항목을 추가하거나 체크인 할 때 적용되는 정리 단계와 git이 작업 디렉토리에 항목을 넣을 때의 얼룩 단계입니다. 여기서 우리의 얼룩은 cat
파일 끝에 후행 줄 바꿈 문자가 없으면 가능한 줄 바꿈 문자를 추가하는 것을 제외하고 는 명령을 통해 내용을 실행 합니다. clean 명령은 공백 필터링으로 http://sed.sourceforge.net/sed1line.txt의 노트와 함께 사용되었습니다 . 쉘 스크립트에 넣어야하는 것 같습니다. 파일 끝의 불필요한 여분의 줄을 git-config 파일에 직접 추가하는 등 sed 명령을 삽입하는 방법을 알 수 없었습니다. (당신 수 있습니다별도의 SED 스크립트의 필요없이, 그러나 후행 공백을 제거, 바로 설정 filter.fix-eol-eof
같은 것으로 sed 's/[ \t]*$//' %f
(가) 어디에 \t
탭을 눌러, 실제 탭입니다.)
require = true는 문제가 발생하면 문제가 발생하지 않도록 오류를 발생시킵니다.
자식에 관한 언어가 정확하지 않은 경우 용서해주십시오. 나는 개념을 상당히 잘 알고 있다고 생각하지만 여전히 용어를 배우고 있습니다.
답변
대상 파일에 후행 공백이 너무 많으면 이전 제안에서 읽을 수없는 커밋을 만드는 경향이 있기 때문에 변경 / 추가 한 행에서 후행 공백 만 제거하는이 사전 커밋 후크를 작성했습니다.
#!/bin/sh
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
IFS='
'
files=$(git diff-index --check --cached $against -- | sed '/^[+-]/d' | perl -pe 's/:[0-9]+:.*//' | uniq)
for file in $files ; do
diff=$(git diff --cached $file)
if test "$(git config diff.noprefix)" = "true"; then
prefix=0
else
prefix=1
fi
echo "$diff" | patch -R -p$prefix
diff=$(echo "$diff" | perl -pe 's/[ \t]+$// if m{^\+}')
out=$(echo "$diff" | patch -p$prefix -f -s -t -o -)
if [ $? -eq 0 ]; then
echo "$diff" | patch -p$prefix -f -t -s
fi
git add $file
done