커밋하기 전에 자식이 후행 공백을 자동으로 제거하도록하십시오. 커밋에서. ~/.gitconfig파일로 다음을 추가하려고했지만 커밋 할

팀과 함께 git을 사용하고 있으며 diff, log, merge 등에서 공백 변경 사항을 제거하고 싶습니다.이 작업을 수행하는 가장 쉬운 방법은 git이 후행 공백 (및 기타 공백 오류)을 자동으로 제거하는 것이라고 가정합니다 ) 적용되는 모든 커밋에서.

~/.gitconfig파일로 다음을 추가하려고했지만 커밋 할 때 아무것도하지 않습니다. 어쩌면 다른 무언가를 위해 설계되었을 수도 있습니다. 해결책은 무엇입니까?

[core]
    whitespace = trailing-space,space-before-tab
[apply]
    whitespace = fix

누구든지 루비 관련 아이디어가있는 경우를 대비하여 루비를 사용하고 있습니다. 커밋하기 전에 자동 코드 형식화는 다음 단계이지만, 어려운 문제이며 실제로 큰 문제를 일으키지 않습니다.



답변

이러한 설정 ( core.whitespaceapply.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와 같다고 가정).

색인을 수정하지만 트리는 수정하지 마십시오

다음 fixwsGit 별칭은 인덱스의 모든 공백 오류를 수정하지만 트리를 건드리지 않습니다.

# 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-indexGit 별명은 색인 및 트리의 모든 공백 오류를 수정합니다 (있는 경우).

# 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

우리가 수동으로 한 경우 :

  1. 설정 apply.whitespacefix(당신은 한 번만 수행하면) :

    git config apply.whitespace fix
    

    이것은 Git에게 패치 에서 공백을 수정하도록 지시 합니다.

  2. Git이 변경 사항을 패치 로 취급하도록 설득 하십시오 .

    git add -up .
    

    각 파일에 대한 모든 변경 사항을 선택하려면 a+ enter를 누르십시오 . Git의 공백 오류 수정에 대한 경고가 표시됩니다.
    ( git -c color.ui=auto diff이 시점에서 색인이 생성되지 않은 변경 사항은 정확히 공백 오류임을 나타냅니다).

  3. 작업 사본에서 공백 오류를 제거하십시오.

    git checkout .
    
  4. 변경 사항을 다시 가져 오십시오 (커밋 할 준비가되지 않은 경우).

    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