path: root/convert.c
diff options
authorEyvind Bernhardsen <>2010-07-02 19:20:47 (GMT)
committerJunio C Hamano <>2010-07-02 22:43:15 (GMT)
commitf217f0e86dc7bacc5dc127982eaadca758b558ce (patch)
treeffd4e74f1b5fb99e6434351354487f2d08c039f3 /convert.c
parent492b10766f499b60bdc867c253f36d274ac51538 (diff)
Avoid conflicts when merging branches with mixed normalization
Currently, merging across changes in line ending normalization is painful since files containing CRLF will conflict with normalized files, even if the only difference between the two versions is the line endings. Additionally, any "real" merge conflicts that exist are obscured because every line in the file has a conflict. Assume you start out with a repo that has a lot of text files with CRLF checked in (A): o---C / \ A---B---D B: Add "* text=auto" to .gitattributes and normalize all files to LF-only C: Modify some of the text files D: Try to merge C You will get a ridiculous number of LF/CRLF conflicts when trying to merge C into D, since the repository contents for C are "wrong" wrt the new .gitattributes file. Fix ll-merge so that the "base", "theirs" and "ours" stages are passed through convert_to_worktree() and convert_to_git() before a three-way merge. This ensures that all three stages are normalized in the same way, removing from consideration differences that are only due to normalization. This feature is optional for now since it changes a low-level mechanism and is not necessary for the majority of users. The "merge.renormalize" config variable enables it. Signed-off-by: Eyvind Bernhardsen <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'convert.c')
1 files changed, 14 insertions, 2 deletions
diff --git a/convert.c b/convert.c
index e41a31e..0203be8 100644
--- a/convert.c
+++ b/convert.c
@@ -93,7 +93,8 @@ static int is_binary(unsigned long size, struct text_stat *stats)
return 0;
-static enum eol determine_output_conversion(enum action action) {
+static enum eol determine_output_conversion(enum action action)
switch (action) {
return EOL_UNSET;
@@ -693,7 +694,8 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)
return !!ATTR_TRUE(value);
-enum action determine_action(enum action text_attr, enum eol eol_attr) {
+static enum action determine_action(enum action text_attr, enum eol eol_attr)
if (text_attr == CRLF_BINARY)
if (eol_attr == EOL_LF)
@@ -773,3 +775,13 @@ int convert_to_working_tree(const char *path, const char *src, size_t len, struc
return ret | apply_filter(path, src, len, dst, filter);
+int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst)
+ int ret = convert_to_working_tree(path, src, len, dst);
+ if (ret) {
+ src = dst->buf;
+ len = dst->len;
+ }
+ return ret | convert_to_git(path, src, len, dst, 0);