5

現在のリリースと次のリリースの core.autocrlf および core.safecrlf 機能については、多くの議論がありました。ここでの質問は、開発者がベア リポジトリからクローンを作成する環境に関するものです。

複製中に autocrlf 設定が有効になります。ただし、開発者はクローンを完全に制御できるため、この autocrlf 設定を削除して続行できます。

  1. .gitattributes ファイルでバイナリ以外のファイルを指定できますが、ファイルがテキスト ファイルかバイナリ ファイルかを GIT が自動的に判断する方法はありますか?

  2. Windows 環境から裸のリポジトリをホストする UNIX マシンに (CRLF を使用して) ファイルをプッシュすることを確認するために配置できる、更新フック (開発者はまだそれを削除できるため、コミット フックは使用できません) のような方法はありますか? UNIX EOL 形式 (LF) に変換されますか?

  3. 各ファイルの CRLF をスキャンする更新フックを使用すると、プッシュ操作のパフォーマンスに影響しますか?

ありがとう

4

1 に答える 1

5
  • 1/ Git 自体には、ファイルがバイナリかテキストかを判断するヒューリスティックがあります ( istextと同様) 。

  • 2/ gergap weblogは最近 (2010 年 5 月) 同じ考えを持っていました。ここで彼の更新フック
    を参照してください(この回答の最後に再現されています)が、トリックは次のとおりです。フックは 、変換しようとするのではなく、不適切な eol スタイルの(おそらく)非バイナリファイルを検出した場合、単にプッシュを拒否します

LF->CRLFWindows でのチェックアウト時に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
于 2010-08-11T06:57:47.770 に答える