1/ Git 自体には、ファイルがバイナリかテキストかを判断するヒューリスティックがあります ( istextと同様) 。
2/ gergap weblogは最近 (2010 年 5 月) 同じ考えを持っていました。ここで彼の更新フック
を参照してください(この回答の最後に再現されています)が、トリックは次のとおりです。フックは
、変換しようとするのではなく、不適切な eol スタイルの(おそらく)非バイナリファイルを検出した場合、単にプッシュを拒否します。
LF->CRLF
Windows でのチェックアウト時にGit が変換します。
ファイルに既に が含まれている場合CRLF
、Git はそれを検出するのに十分なほど賢く、問題のある部分に展開しませんCRCRLF
。を保持しCRLF
ます。これは、チェックアウト中にファイルがローカルで暗黙的に変更されたことを意味します。これは、ファイルを再度コミットすると、間違いCRLF
が に修正されるためLF
です。そのため、GIT はこれらのファイルを変更済みとしてマークする必要があります。
問題を理解するのは良いことですが、間違った行末が中央リポジトリにプッシュされるのを防ぐソリューションが必要です。
解決策は、中央サーバーに更新フックをインストールすることです。
- 3/ わずかなコストがかかりますが、30 秒ごとにプッシュしない限り問題にはなりません。
さらに、実際の変換は行われません。ファイルが正しくない場合、プッシュは拒否されます。
これにより、変換の問題が本来あるべき場所、つまり開発者側に戻されます。
#!/bin/sh
#
# Author: Gerhard Gappmeier, ascolab GmbH
# This script is based on the update.sample in git/contrib/hooks.
# You are free to use this script for whatever you want.
#
# To enable this hook, rename this file to "update".
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
#echo "COMMANDLINE: $*"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
BINARAY_EXT="pdb dll exe png gif jpg"
# returns 1 if the given filename is a binary file
function IsBinary()
{
result=0
for ext in $BINARAY_EXT; do
if [ "$ext" = "${1#*.}" ]; then
result=1
break
fi
done
return $result
}
# make temp paths
tmp=$(mktemp /tmp/git.update.XXXXXX)
log=$(mktemp /tmp/git.update.log.XXXXXX)
tree=$(mktemp /tmp/git.diff-tree.XXXXXX)
ret=0
git diff-tree -r "$oldrev" "$newrev" > $tree
#echo
#echo diff-tree:
#cat $tree
# read $tree using the file descriptors
exec 3<&0
exec 0<$tree
while read old_mode new_mode old_sha1 new_sha1 status name
do
# debug output
#echo "old_mode=$old_mode new_mode=$new_mode old_sha1=$old_sha1 new_sha1=$new_sha1 status=$status name=$name"
# skip lines showing parent commit
test -z "$new_sha1" && continue
# skip deletions
[ "$new_sha1" = "0000000000000000000000000000000000000000" ] && continue
# don't do a CRLF check for binary files
IsBinary $tmp
if [ $? -eq 1 ]; then
continue # skip binary files
fi
# check for CRLF
git cat-file blob $new_sha1 > $tmp
RESULT=`grep -Pl '\r\n' $tmp`
echo $RESULT
if [ "$RESULT" = "$tmp" ]; then
echo "###################################################################################################"
echo "# '$name' contains CRLF! Dear Windows developer, please activate the GIT core.autocrlf feature,"
echo "# or change the line endings to LF before trying to push."
echo "# Use 'git config core.autocrlf true' to activate CRLF conversion."
echo "# OR use 'git reset HEAD~1' to undo your last commit and fix the line endings."
echo "###################################################################################################"
ret=1
fi
done
exec 0<&3
# --- Finished
exit $ret