End-of-line normalization, getting close?
v4 cover End-of-line normalization, getting close?
Here's the latest series. Linus's suggested attribute names were a lot saner than mine, so I've now split the "crlf" attribute into "crlf" and "eol", and the "crlf" attribute gets renamed to "text" in the final commit. I dropped the patch that renamed autocrlf.
git-cvsserver gets a bit more love in this round (particularly the documentation), so I think it should work as well as it did before. Not too happy with the logic duplication, though.
Patch 1/4 is still "safe autocrlf" from Finn Arne, just for convenience.
All in all, I think this looks pretty good now.
Signature · 24 lines
Eyvind Eyvind Bernhardsen (3): Add tests for per-repository eol normalization Add per-repository eol normalization Rename the "crlf" attribute "text" Finn Arne Gangstad (1): autocrlf: Make it work also for un-normalized repositories Documentation/config.txt | 20 +++-- Documentation/git-cvsserver.txt | 13 +-- Documentation/gitattributes.txt | 164 +++++++++++++++++++++++++++++++-------- attr.c | 2 +- cache.h | 9 ++- config.c | 2 +- convert.c | 155 +++++++++++++++++++++++++++++++------ environment.c | 2 +- git-cvsserver.perl | 13 ++- t/t0020-crlf.sh | 52 ++++++++++++ t/t0025-crlf-auto.sh | 156 +++++++++++++++++++++++++++++++++++++ 11 files changed, 507 insertions(+), 81 deletions(-) create mode 100755 t/t0025-crlf-auto.sh
PATCH v4 1/4 autocrlf: Make it work also for un-normalized repositories
From: Finn Arne Gangstad <[email protected]>
Previously, autocrlf would only work well for normalized repositories. Any text files that contained CRLF in the repository would cause problems, and would be modified when handled with core.autocrlf set.
Change autocrlf to not do any conversions to files that in the repository already contain a CR. git with autocrlf set will never create such a file, or change a LF only file to contain CRs, so the (new) assumption is that if a file contains a CR, it is intentional, and autocrlf should not change that.
The following sequence should now always be a NOP even with autocrlf set (assuming a clean working directory):
git checkout <something>
touch *
git add -A . (will add nothing)
git commit (nothing to commit)
Previously this would break for any text file containing a CR.
Some of you may have been folowing Eyvind's excellent thread about trying to make end-of-line translation in git a bit smoother.
I decided to attack the problem from a different angle: Is it possible to make autocrlf behave non-destructively for all the previous problem cases?
Stealing the problem from Eyvind's initial mail (paraphrased and summarized a bit):
1. Setting autocrlf globally is a pain since autocrlf does not work well with CRLF in the repo
2. Setting it in individual repos is hard since you do it "too late" (the clone will get it wrong)
3. If someone checks in a file with CRLF later, you get into problems again
4. If a repository once has contained CRLF, you can't tell autocrlf at which commit everything is sane again
5. autocrlf does needless work if you know that all your users want the same EOL style.
I belive that this patch makes autocrlf a safe (and good) default setting for Windows, and this solves problems 1-4 (it solves 2 by being set by default, which is early enough for clone).
I implemented it by looking for CR charactes in the index, and aborting any conversion attempt if this is found.
--- convert.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ t/t0020-crlf.sh | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 0 deletions(-)
convert.c +49 -0
@@ -120,6 +120,43 @@ static void check_safe_crlf(const char *path, int action, } } +static int has_cr_in_index (const char *path) +{ +int pos, len; +unsigned long sz; +enum object_type type; +void *data; +int has_cr; +struct index_state *istate = &the_index; + + len =strlen (path); + pos =index_name_pos (istate, path, len); +if (pos <0 ) { +/* +* We might be in the middle of a merge, in which +* case we would read stage #2 (ours). +*/ +int i; +for (i = -pos -1 ; + (pos <0 && i < istate->cache_nr && + !strcmp (istate->cache[i]->name, path)); + i++) +if (ce_stage (istate->cache[i]) ==2 ) + pos = i; + } +if (pos <0 ) +return 0 ; + data =read_sha1_file (istate->cache[pos]->sha1, &type, &sz); +if (!data || type !=OBJ_BLOB ) { +free (data); +return 0 ; + } + + has_cr =memchr (data,'\r' , sz) !=NULL ; +free (data); +return has_cr; +} +static int crlf_to_git (const char *path,const char *src,size_t len,struct strbuf *buf,int action,enum safe_crlf checksafe) {
@@ -145,6 +182,13 @@ static int crlf_to_git(const char *path, const char *src, size_t len,*/ if (is_binary (len, &stats))return 0 ; + +/* +* If the file in the index has any CR in it, do not convert. +* This is the new safer autocrlf handling. +*/ +if (has_cr_in_index (path)) +return 0 ; }check_safe_crlf (path, action, &stats, checksafe);
@@ -203,6 +247,11 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,return 0 ;if (action ==CRLF_GUESS ) { +/* If we have any CR or CRLF line endings, we do not touch it */ +/* This is the new safer autocrlf-handling */ +if (stats.cr >0 || stats.crlf >0 ) +return 0 ; +/* If we have any bare CR characters, we're not going to touch it */ if (stats.cr != stats.crlf)return 0 ;
t/t0020-crlf.sh +52 -0
57 lines not on this page · raw message
Signature · 1 line
1.7.1.5.gd739a
PATCH v4 2/4 Add tests for per-repository eol normalization
In reply to Eyvind Bernhardsen--- t/t0025-crlf-auto.sh | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 143 insertions(+), 0 deletions(-) create mode 100755 t/t0025-crlf-auto.sh
t/t0025-crlf-auto.sh new file +143 -0
@@ -0,0 +1,143 @@ +#!/bin/sh + +test_description='CRLF conversion' + +. ./test-lib.sh + +has_cr() { + tr '\015' Q <"$1" | grep Q >/dev/null +} + +test_expect_success setup ' + + git config core.autocrlf false && + + for w in Hello world how are you; do echo $w; done >one && + for w in I am very very fine thank you; do echo ${w}Q; done | q_to_cr >two && + for w in Oh here is a QNUL byte how alarming; do echo ${w}; done | q_to_nul >three && + git add . && + + git commit -m initial && + + one=`git rev-parse HEAD:one` && + two=`git rev-parse HEAD:two` && + + for w in Some extra lines here; do echo $w; done >>one && + git diff >patch.file && + patched=`git hash-object --stdin <one` && + git read-tree --reset -u HEAD && + + echo happy. +' + +test_expect_success 'default settings cause no changes' ' + + rm -f .gitattributes tmp one two && + git read-tree --reset -u HEAD && + + ! has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -z "$twodiff" +' + +test_expect_failure 'crlf=true causes a CRLF file to be normalized' ' + + rm -f .gitattributes tmp one two && + echo "two crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + # Note, "normalized" means that git will normalize it if added + has_cr two && + twodiff=`git diff two` && + test -n "$twodiff" +' + +test_expect_failure 'eol=crlf gives a normalized file CRLFs with autocrlf=false' ' + + rm -f .gitattributes tmp one two && + git config core.autocrlf false && + echo "one eol=crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr one && + onediff=`git diff one` && + test -z "$onediff" +' + +test_expect_failure 'eol=crlf gives a normalized file CRLFs with autocrlf=input' ' + + rm -f .gitattributes tmp one two && + git config core.autocrlf input && + echo "one eol=crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr one && + onediff=`git diff one` && + test -z "$onediff" +' + +test_expect_failure 'eol=lf gives a normalized file LFs with autocrlf=true' ' + + rm -f .gitattributes tmp one two && + git config core.autocrlf true && + echo "one eol=lf" > .gitattributes && + git read-tree --reset -u HEAD && + + ! has_cr one && + onediff=`git diff one` && + test -z "$onediff" +' + +test_expect_success 'autocrlf=true does not normalize CRLF files' ' + + rm -f .gitattributes tmp one two && + git config core.autocrlf true && + git read-tree --reset -u HEAD && + + has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -z "$twodiff" +' + +test_expect_failure 'crlf=auto, autocrlf=true _does_ normalize CRLF files' ' + + rm -f .gitattributes tmp one two && + git config core.autocrlf true && + echo "* crlf=auto" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -n "$twodiff" +' + +test_expect_success 'crlf=auto, autocrlf=true does not normalize binary files' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf true && + echo "* crlf=auto" > .gitattributes && + git read-tree --reset -u HEAD && + + ! has_cr three && + threediff=`git diff three` && + test -z "$threediff" +' + +test_expect_failure 'eol=crlf _does_ normalize binary files' ' + + rm -f .gitattributes tmp one two three && + echo "three eol=crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr three && + threediff=`git diff three` && + test -z "$threediff" +' + +test_done
Signature · 1 line
1.7.1.5.gd739a
PATCH v4 3/4 Add per-repository eol normalization
In reply to Eyvind BernhardsenChange the semantics of the "crlf" attribute so that it enables end-of-line normalization when it is set, regardless of "core.autocrlf".
Add a new setting for "crlf": "auto", which enables end-of-line conversion but does not override the automatic text file detection.
Add a new attribute "eol" with possible values "crlf" and "lf". When set, this attribute enables normalization and forces git to use CRLF or LF line endings in the working directory, respectively.
The line ending style to be used for normalized text files in the working directory is set using "core.autocrlf". When it is set to "true", CRLFs are used in the working directory; when set to "input" or "false", LFs are used.
--- Documentation/config.txt | 4 +- Documentation/gitattributes.txt | 153 +++++++++++++++++++++++++++++++-------- cache.h | 9 ++- config.c | 2 +- convert.c | 117 +++++++++++++++++++++--------- environment.c | 2 +- t/t0025-crlf-auto.sh | 12 ++-- 7 files changed, 223 insertions(+), 76 deletions(-)
Documentation/config.txt +2 -2
@@ -208,8 +208,8 @@ core.autocrlf:: based on the file's contents. See linkgit:gitattributes[5]. core.safecrlf:: - If true, makes git check if converting `CRLF` as controlled by - `core.autocrlf` is reversible. Git will verify if a command + If true, makes git check if converting `CRLF` is reversible when + end-of-line conversion is active. Git will verify if a command modifies a file in the work tree either directly or indirectly. For example, committing a file followed by checking out the same file should yield the original file in the work tree. If
Documentation/gitattributes.txt +114 -25
164 lines not on this page · raw message
cache.h +8 -1
@@ -547,7 +547,6 @@ extern int core_compression_seen;extern size_t packed_git_window_size;extern size_t packed_git_limit;extern size_t delta_base_cache_limit; -extern int auto_crlf;extern int read_replace_refs;extern int fsync_object_files;extern int core_preload_index;
@@ -561,6 +560,14 @@ enum safe_crlf {extern enum safe_crlf safe_crlf; +enum auto_crlf { +AUTO_CRLF_FALSE =0 , +AUTO_CRLF_TRUE =1 , +AUTO_CRLF_INPUT =-1 , +}; + +extern enum auto_crlf auto_crlf; +enum branch_track {BRANCH_TRACK_UNSPECIFIED =-1 ,BRANCH_TRACK_NEVER =0 ,
config.c +1 -1
@@ -461,7 +461,7 @@ static int git_default_core_config(const char *var, const char *value)if (!strcmp (var,"core.autocrlf" )) {if (value && !strcasecmp (value,"input" )) { - auto_crlf =-1 ; + auto_crlf =AUTO_CRLF_INPUT ;return 0 ; } auto_crlf =git_config_bool (var, value);
convert.c +84 -33
254 lines not on this page · raw message
environment.c +1 -1
@@ -38,7 +38,7 @@ const char *pager_program;int pager_use_color =1 ;const char *editor_program;const char *excludes_file; -int auto_crlf =0 ;/* 1: both ways, -1: only when adding git objects */ +enum auto_crlf auto_crlf =AUTO_CRLF_FALSE ;int read_replace_refs =1 ;enum safe_crlf safe_crlf =SAFE_CRLF_WARN ;unsigned whitespace_rule_cfg =WS_DEFAULT_RULE ;
t/t0025-crlf-auto.sh +6 -6
@@ -42,7 +42,7 @@ test_expect_success 'default settings cause no changes' ' test -z "$onediff" -a -z "$twodiff" ' -test_expect_failure 'crlf=true causes a CRLF file to be normalized' ' +test_expect_success 'crlf=true causes a CRLF file to be normalized' ' rm -f .gitattributes tmp one two && echo "two crlf" > .gitattributes &&
@@ -54,7 +54,7 @@ test_expect_failure 'crlf=true causes a CRLF file to be normalized' ' test -n "$twodiff" ' -test_expect_failure 'eol=crlf gives a normalized file CRLFs with autocrlf=false' ' +test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=false' ' rm -f .gitattributes tmp one two && git config core.autocrlf false &&
@@ -66,7 +66,7 @@ test_expect_failure 'eol=crlf gives a normalized file CRLFs with autocrlf=false' test -z "$onediff" ' -test_expect_failure 'eol=crlf gives a normalized file CRLFs with autocrlf=input' ' +test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=input' ' rm -f .gitattributes tmp one two && git config core.autocrlf input &&
@@ -78,7 +78,7 @@ test_expect_failure 'eol=crlf gives a normalized file CRLFs with autocrlf=input' test -z "$onediff" ' -test_expect_failure 'eol=lf gives a normalized file LFs with autocrlf=true' ' +test_expect_success 'eol=lf gives a normalized file LFs with autocrlf=true' ' rm -f .gitattributes tmp one two && git config core.autocrlf true &&
@@ -103,7 +103,7 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' ' test -z "$onediff" -a -z "$twodiff" ' -test_expect_failure 'crlf=auto, autocrlf=true _does_ normalize CRLF files' ' +test_expect_success 'crlf=auto, autocrlf=true _does_ normalize CRLF files' ' rm -f .gitattributes tmp one two && git config core.autocrlf true &&
@@ -129,7 +129,7 @@ test_expect_success 'crlf=auto, autocrlf=true does not normalize binary files' ' test -z "$threediff" ' -test_expect_failure 'eol=crlf _does_ normalize binary files' ' +test_expect_success 'eol=crlf _does_ normalize binary files' ' rm -f .gitattributes tmp one two three && echo "three eol=crlf" > .gitattributes &&
Signature · 1 line
1.7.1.5.gd739a
PATCH v4 4/4 Rename the "crlf" attribute "text"
In reply to Eyvind BernhardsenAs discussed on the list, "crlf" is not an optimal name. Linus suggested "text", which is much better.
--- Documentation/config.txt | 16 ++++++---- Documentation/git-cvsserver.txt | 13 +++----- Documentation/gitattributes.txt | 59 +++++++++++++++++++++++---------------- attr.c | 2 +- convert.c | 23 ++++++++++----- git-cvsserver.perl | 13 ++++++-- t/t0025-crlf-auto.sh | 21 +++++++++++-- 7 files changed, 91 insertions(+), 56 deletions(-)
Documentation/config.txt +9 -7
@@ -204,7 +204,7 @@ core.autocrlf:: reading from the work tree but files are written out to the work tree with `LF` at the end of lines. A file is considered "text" (i.e. be subjected to the autocrlf mechanism) based on - the file's `crlf` attribute, or if `crlf` is unspecified, + the file's `text` attribute, or if `text` is unspecified, based on the file's contents. See linkgit:gitattributes[5]. core.safecrlf::
@@ -975,13 +975,15 @@ gitcvs.logfile:: various stuff. See linkgit:git-cvsserver[1]. gitcvs.usecrlfattr:: - If true, the server will look up the `crlf` attribute for - files to determine the '-k' modes to use. If `crlf` is set, - the '-k' mode will be left blank, so cvs clients will - treat it as text. If `crlf` is explicitly unset, the file + If true, the server will look up the end-of-line conversion + attributes for files to determine the '-k' modes to use. If + the attributes force git to treat a file as text, + the '-k' mode will be left blank so cvs clients will + treat it as text. If they suppress text conversion, the file will be set with '-kb' mode, which suppresses any newline munging - the client might otherwise do. If `crlf` is not specified, - then 'gitcvs.allbinary' is used. See linkgit:gitattributes[5]. + the client might otherwise do. If the attributes do not allow + the file type to be determined, then 'gitcvs.allbinary' is + used. See linkgit:gitattributes[5]. gitcvs.allbinary:: This is used if 'gitcvs.usecrlfattr' does not resolve
Documentation/git-cvsserver.txt +5 -8
@@ -340,16 +340,13 @@ By default the server leaves the '-k' mode blank for all files, which causes the cvs client to treat them as a text files, subject to crlf conversion on some platforms. -You can make the server use `crlf` attributes to set the '-k' modes -for files by setting the `gitcvs.usecrlfattr` config variable. -In this case, if `crlf` is explicitly unset ('-crlf'), then the -server will set '-kb' mode for binary files. If `crlf` is set, -then the '-k' mode will explicitly be left blank. See -also linkgit:gitattributes[5] for more information about the `crlf` -attribute. +You can make the server use the end-of-line conversion attributes to +set the '-k' modes for files by setting the `gitcvs.usecrlfattr` +config variable. See linkgit:gitattributes[5] for more information +about end-of-line conversion. Alternatively, if `gitcvs.usecrlfattr` config is not enabled -or if the `crlf` attribute is unspecified for a filename, then +or the attributes do not allow automatic detection for a filename, then the server uses the `gitcvs.allbinary` config for the default setting. If `gitcvs.allbinary` is set, then file not otherwise specified will default to '-kb' mode. Otherwise the '-k' mode
Documentation/gitattributes.txt +35 -24
173 lines not on this page · raw message
attr.c +1 -1
@@ -287,7 +287,7 @@ static void free_attr_elem(struct attr_stack *e) }static const char *builtin_attr[] = { -"[attr]binary -diff -crlf" , +"[attr]binary -diff -text" ,NULL , };
convert.c +15 -8
@@ -440,12 +440,14 @@ static int read_convert_config(const char *var, const char *value, void *cb)static void setup_convert_check (struct git_attr_check *check) { +static struct git_attr *attr_text;static struct git_attr *attr_crlf;static struct git_attr *attr_eol;static struct git_attr *attr_ident;static struct git_attr *attr_filter; -if (!attr_crlf) { +if (!attr_text) { + attr_text =git_attr ("text" ); attr_crlf =git_attr ("crlf" ); attr_eol =git_attr ("eol" ); attr_ident =git_attr ("ident" );
@@ -457,6 +459,7 @@ static void setup_convert_check(struct git_attr_check *check) check[1 ].attr = attr_ident; check[2 ].attr = attr_filter; check[3 ].attr = attr_eol; + check[4 ].attr = attr_text; }static int count_ident (const char *cp,unsigned long size)
@@ -652,20 +655,20 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)return !!ATTR_TRUE (value); } -enum action determine_action (enum action crlf_attr,enum eol eol_attr) { -if (crlf_attr ==CRLF_BINARY ) +enum action determine_action (enum action text_attr,enum eol eol_attr) { +if (text_attr ==CRLF_BINARY )return CRLF_BINARY ;if (eol_attr ==EOL_LF )return CRLF_INPUT ;if (eol_attr ==EOL_CRLF )return CRLF_CRLF ; -return crlf_attr; +return text_attr; }int convert_to_git (const char *path,const char *src,size_t len,struct strbuf *dst,enum safe_crlf checksafe) { -struct git_attr_check check[4 ]; +struct git_attr_check check[5 ];enum action action =CRLF_GUESS ;enum eol eol =EOL_UNSET ;int ident =0 , ret =0 ;
@@ -674,7 +677,9 @@ int convert_to_git(const char *path, const char *src, size_t len,setup_convert_check (check);if (!git_checkattr (path,ARRAY_SIZE (check), check)) {struct convert_driver *drv; - action =git_path_check_crlf (path, check +0 ); + action =git_path_check_crlf (path, check +4 ); +if (action ==CRLF_GUESS ) + action =git_path_check_crlf (path, check +0 ); ident =git_path_check_ident (path, check +1 ); drv =git_path_check_convert (path, check +2 ); eol =git_path_check_eol (path, check +3 );
@@ -698,7 +703,7 @@ int convert_to_git(const char *path, const char *src, size_t len,int convert_to_working_tree (const char *path,const char *src,size_t len,struct strbuf *dst) { -struct git_attr_check check[4 ]; +struct git_attr_check check[5 ];enum action action =CRLF_GUESS ;enum eol eol =EOL_UNSET ;int ident =0 , ret =0 ;
@@ -707,7 +712,9 @@ int convert_to_working_tree(const char *path, const char *src, size_t len, strucsetup_convert_check (check);if (!git_checkattr (path,ARRAY_SIZE (check), check)) {struct convert_driver *drv; - action =git_path_check_crlf (path, check +0 ); + action =git_path_check_crlf (path, check +4 ); +if (action ==CRLF_GUESS ) + action =git_path_check_crlf (path, check +0 ); ident =git_path_check_ident (path, check +1 ); drv =git_path_check_convert (path, check +2 ); eol =git_path_check_eol (path, check +3 );
git-cvsserver.perl +9 -4
@@ -2369,15 +2369,20 @@ sub kopts_from_path if ( defined ( $cfg->{gitcvs}{usecrlfattr} ) and $cfg->{gitcvs}{usecrlfattr} =~ /\s*(1|true|yes)\s*$/i ) { - my ($val) = check_attr( "crlf", $path ); - if ( $val eq "set" ) + my ($val) = check_attr( "text", $path ); + if ( $val eq "unspecified" ) { - return ""; + $val = check_attr( "crlf", $path ); } - elsif ( $val eq "unset" ) + if ( $val eq "unset" ) { return "-kb" } + elsif ( check_attr( "eol", $path ) ne "unspecified" || + $val eq "set" || $val eq "input" ) + { + return ""; + } else { $log->info("Unrecognized check_attr crlf $path : $val");
t/t0025-crlf-auto.sh +17 -4
@@ -44,6 +44,7 @@ test_expect_success 'default settings cause no changes' ' test_expect_success 'crlf=true causes a CRLF file to be normalized' ' + # Backwards compatibility check rm -f .gitattributes tmp one two && echo "two crlf" > .gitattributes && git read-tree --reset -u HEAD &&
@@ -54,6 +55,18 @@ test_expect_success 'crlf=true causes a CRLF file to be normalized' ' test -n "$twodiff" ' +test_expect_success 'text=true causes a CRLF file to be normalized' ' + + rm -f .gitattributes tmp one two && + echo "two text" > .gitattributes && + git read-tree --reset -u HEAD && + + # Note, "normalized" means that git will normalize it if added + has_cr two && + twodiff=`git diff two` && + test -n "$twodiff" +' + test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=false' ' rm -f .gitattributes tmp one two &&
@@ -103,11 +116,11 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' ' test -z "$onediff" -a -z "$twodiff" ' -test_expect_success 'crlf=auto, autocrlf=true _does_ normalize CRLF files' ' +test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' ' rm -f .gitattributes tmp one two && git config core.autocrlf true && - echo "* crlf=auto" > .gitattributes && + echo "* text=auto" > .gitattributes && git read-tree --reset -u HEAD && has_cr one &&
@@ -117,11 +130,11 @@ test_expect_success 'crlf=auto, autocrlf=true _does_ normalize CRLF files' ' test -z "$onediff" -a -n "$twodiff" ' -test_expect_success 'crlf=auto, autocrlf=true does not normalize binary files' ' +test_expect_success 'text=auto, autocrlf=true does not normalize binary files' ' rm -f .gitattributes tmp one two three && git config core.autocrlf true && - echo "* crlf=auto" > .gitattributes && + echo "* text=auto" > .gitattributes && git read-tree --reset -u HEAD && ! has_cr three &&
Signature · 1 line
1.7.1.5.gd739a