git-merge 是否可以忽略行尾差异? [英] Is it possible for git-merge to ignore line-ending differences?

查看:20
本文介绍了git-merge 是否可以忽略行尾差异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

git merge 是否可以忽略行尾差异?

也许我问错了问题……但是:

我尝试使用 config.crlf input 但事情变得有点混乱和失控,特别是当我事后应用它时.

一方面,事后应用此配置似乎不会影响应用此选项之前提交到存储库的文件.另一件事是,现在突然所有提交都会导致大量关于 CRLF 转换为 LF 的恼人警告消息.

老实说,我并不在乎使用什么行尾,我个人更喜欢 Unix 风格的 ,但无论如何.我所关心的只是让 git merge 变得更聪明一点,并忽略行尾的差异.

有时我有两个相同的文件,但 git 会将它们标记为冲突(并且冲突是整个文件),因为它们使用不同的行结束字符.

更新:

我发现 git diff 接受 --ignore-space-at-eol 选项,是否可以让 git merge> 也使用这个选项?

解决方案

2013 年更新:

最近的 git 版本授权使用合并策略 recursive 和策略 option (-X):

但是使用-Xignore-space-change";也是一种可能性

  • Fab-V 提到了 下面:

    git merge master -s recursive -X renormalize


jakub.g评论 策略也适用于樱桃采摘强>:

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize

这比 ignore-all-space 效果更好.


在 Git 2.29(2020 年第四季度)之前,所有合并"内部使用合并递归机制的操作应该遵守 merge.renormalize 配置,但其中许多没有.

参见 commit 00906d6提交 8d55225f6e7cfb57d72a0a7cfb5732a0cfb5732a0cfb5732a0c6f6e7cfcommit fe48efb(2020 年 8 月 3 日)由 以利亚纽伦 (newren).
(由 Junio C Hamano 合并 -- gitster --commit 4339259,2020 年 8 月 10 日)

<块引用>

merge: make merge.renormalize 适用于合并机器的所有用途

签字人:Elijah Newren

<块引用>

'merge' 命令并不是唯一一个进行合并的命令;checkout -m 或 rebase 等其他命令也可以.

不幸的是,检查merge.renormalize"的唯一代码区域是配置设置在 builtin/merge.c,意味着它只能影响由merge"执行的合并.命令.

将此配置设置的处理移至 merge_recursive_config() 以便其他命令也可以从中受益.


原始答案(2009 年 5 月)

忽略eol样式的补丁已经在2007 年 6 月,但它只涉及 git diff --ignore-space-at-eol,而不是 git merge.

当时有人问过这个问题:

<块引用>

--ignore-space-at-eol 应该是 git-merge 的一个选项吗?
合并是此功能重要的地方.
具有这些选项的自动解析合并的语义是什么——它们仅用于重命名检测,还是我们例如不标记仅与空格更改的冲突?如果我们不接受,我们会自动接受哪个版本?

Julio C Hamano 并不十分热情:

<块引用>

这当然很诱人,但我怀疑这应该留给以后的几轮.
我怀疑它会引入两种不同类型差异的概念,一种是机械处理的(即与git-merge-recursive"合并使用,并应用git-am"),另一个需要人类检查才能理解.
对于后一种情况,修改输入通常很有用,即使比较修改后的输入文件的输出可能不容易用于机械应用.

总体思路,当涉及到git merge时,就是依赖第三方合并工具.

例如,我已经将 DiffMerge 设置为 Git 合并的工具,设置了规则集 允许合并工具忽略某些类型文件的 eol.


在 Windows 上设置,使用 MSysGit1.6.3,用于 DOS 或 Git bash 会话,使用 DiffMerge 或 KDiff3:

  • 在您的 PATH 中设置一个目录(此处:c:HOMEWAREcmd).
  • 在该目录中添加脚本 merge.sh(您最喜欢的合并工具的包装器)

merge.sh:

#!/bin/sh# 将以下参数传递给mergetool:# 本地基础远程merge_result本地=$1基数=$2远程=$3结果=$4如果 [ -f $base ]然后#C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe"$alocal"$base"$远程"-m --result=$result"--title1=我的"--title2=合并到:$result";--title3=他们的"# 对于合并尊重 eol,KDiff3 比 DiffMerge 更好(它总是将 LF 转换为 CRLF)# KDiff3 将显示 eol 选项(如果 Windows:CRLF,如果 Unix LF)C:/Program Files/KDiff3/kdiff3.exe"-m "$base";$alocal"$远程"-o "$result";别的# 并不总是有一个共同的祖先:DiffMerge 需要 3 个文件,BASE 将是结果#C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe"$alocal"$结果"$远程"-m --result=$result"--title1=我的"--title2=合并到:$result";--title3=他们的"# KDiff3 然而知道如何基于 2 个文件(不仅仅是 3 个)进行合并C:/Program Files/KDiff3/kdiff3.exe"-m "$base";$远程"-o "$result";菲

  • 声明您的 Git 合并包装器

Git 配置命令:

git config --global merge.tool diffmergegit config --global mergetool.diffmerge.cmd "merge.sh "$PWD/$LOCAL";$PWD/$BASE"$PWD/$REMOTE"$PWD/$MERGED"git config --global mergetool.diffmerge.trustExitCode falsegit config --global mergetool.diffmerge.keepBackup false

  • 检查 autoCRLF 是否为假

系统级别的 git 配置:

git config ---system core.autoCRLF=false

  • 测试,当两行相同(但它们的 eol 字符相同)时,DiffMerge 或 KDiff3 将在合并期间忽略这些行.

DOS 脚本(注意:dos2unix 命令来自这里,用于模拟 Unix eol-样式.该命令已复制到本答案开头提到的目录中.):

C:HOMEWAREgit	est>mkdir test_mergeC:HOMEWAREgit	est>cd test_mergeC:HOMEWAREgit	est	est_merge>git initC:HOMEWAREgit	est	est_merge>echo a1>a.txt &回声 a2 >>一个.txtC:HOMEWAREgit	est	est_merge>git add a.txtC:HOMEWAREgit	est	est_merge>git commit -m "a.txt, windows eol style";C:HOMEWAREgit	est	est_merge>git checkout -b windows切换到新分支windows"C:HOMEWAREgit	est	est_merge>echo a3 >>a.txt &回声 a4 >>一个.txtC:HOMEWAREgit	est	est_merge>git add a.txtC:HOMEWAREgit	est	est_merge>git commit -m添加两行,windows eol样式"C:HOMEWAREgit	est	est_merge>git checkout masterC:HOMEWAREgit	est	est_merge>git checkout -b unix切换到一个新的分支 'unix'C:HOMEWAREgit	est	est_merge>echo au3>>a.txt &回声 au4 >>a.txt &&回声au5 >>一个.txtC:HOMEWAREgit	est	est_merge>dos2unix a.txtDos2Unix:处理文件 a.txt ...C:HOMEWAREgit	est	est_merge>git add a.txtC:HOMEWAREgit	est	est_merge>git commit -m添加3行,所有文件unix eol样式"[unix c433a63] 添加3行,所有文件unix eol样式C:HOMEWAREgit	est	est_merge>git 合并窗口自动合并a.txtCONFLICT(内容):合并 a.txt 中的冲突自动合并失败;修复冲突,然后提交结果.C:HOMEWAREgit	est	est_merge>git ls-files -u100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txtC:HOMEWAREgit	est	est_merge>git mergetool合并文件:a.txt'a.txt' 的正常合并冲突:{local}:修改{远程}:修改点击返回以启动合并解析工具(diffmerge):

此时(点击返回"),DiffMerge 或 KDiff3 将打开,您将亲眼看到哪些行实际合并,哪些行被忽略.

警告:结果文件将始终处于带有 DiffMerge 的 Windows eol 模式 (CRLF)...
KDiff3 提供以一种或另一种方式保存.

Is it possible for git merge to ignore line-ending differences?

Maybe I'm asking the wrong question ... but:

I tried uisng config.crlf input but things got a bit messy and out of control, specially when I applied it after the fact.

For one thing, applying this config after the fact doesn't seem to affect files that were committed to the repository before applying this option. Another thing is that suddenly all commits now result in lots of annoying warning messages about CRLF being converted to LF.

To be honest, I don't really care what line-ending is used, I personally prefer the Unix style , but whatever. All I care about, is for git merge to be a bit smarter and ignore the differences in line-endings.

Sometimes I have two identical files, but git would mark them as being in conflict (and the conflict is the whole file) simply because they use a different line ending character.

Update:

I found out that git diff accepts a --ignore-space-at-eol option, would it be possible to let git merge use this option as well?

解决方案

Update 2013:

More recent git versions authorize using merge with strategy recursive and strategy option (-X):

But using "-Xignore-space-change" is also a possibility

  • Fab-V mentions below:

    git merge master -s recursive -X renormalize
    


jakub.g also comments that the strategies work also with cherry-picking:

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

This works much better than ignore-all-space.


Before Git 2.29 (Q4 2020), All "mergy" operations that internally use the merge-recursive machinery should honor the merge.renormalize configuration, but many of them didn't.

See commit 00906d6, commit 8d55225, commit 6f6e7cf, commit fe48efb (03 Aug 2020) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit 4339259, 10 Aug 2020)

merge: make merge.renormalize work for all uses of merge machinery

Signed-off-by: Elijah Newren

The 'merge' command is not the only one that does merges; other commands like checkout -m or rebase do as well.

Unfortunately, the only area of the code that checked for the "merge.renormalize" config setting was in builtin/merge.c, meaning it could only affect merges performed by the "merge" command.

Move the handling of this config setting to merge_recursive_config() so that other commands can benefit from it as well.


Original answer (May 2009)

The patch for ignoring eol style has been proposed in June 2007, but it only concerns git diff --ignore-space-at-eol, not git merge.

At the time, the question has been askeed:

Should --ignore-space-at-eol be an option to git-merge ?
Merges are where this functionality matters.
What are the semantics of an auto-resolved merge with those options in effect -- are they only used for rename detection, or do we, e.g., not flag conflicts with only whitespace changes ? And if we don't, which version do we accept automatically ?

Julio C Hamano was not exactly enthusiastic:

This certainly is tempting, but I suspect that should be left to later rounds.
I suspect that it would introduce a concept of two different kinds of diffs, one to be mechanically processed (i.e. use in merge with "git-merge-recursive", and apply with "git-am"), and another to be inspected by humans to understand.
It often may be useful to munge the input for the latter case, even though the output from comparing munged input files may not be readily usable for mechanical application.

The general idea, when it comes to git merge, is to rely on the third-party merge tool.

For instance, I have setup DiffMerge to be the tool for Git merge, setting a ruleset which allow that merge tool to ignore eol for certain type of files.


Setup on Windows, with MSysGit1.6.3, either for DOS or Git bash session, with DiffMerge or KDiff3:

  • set a directory into your PATH (here: c:HOMEWAREcmd).
  • add in that directory the script merge.sh (wrapper for your favorite merge tool)

merge.sh:

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"
    
    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi

  • Declare your merge wrapper for Git

Git config commands:

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh "$PWD/$LOCAL" "$PWD/$BASE" "$PWD/$REMOTE" "$PWD/$MERGED"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false

  • Check that autoCRLF is false

git config at system level:

git config ---system core.autoCRLF=false

  • Test that, when two lines are identical (but their eol chars), both DiffMerge or KDiff3 will ignore those line during a merge.

DOS script (note: the dos2unix command comes from here, and is used to simulate a Unix eol-style. That command has been copied in the directory mentioned at the beginning of this answer.):

C:HOMEWAREgit	est>mkdir test_merge
C:HOMEWAREgit	est>cd test_merge
C:HOMEWAREgit	est	est_merge>git init
C:HOMEWAREgit	est	est_merge>echo a1 > a.txt & echo a2 >> a.txt
C:HOMEWAREgit	est	est_merge>git add a.txt
C:HOMEWAREgit	est	est_merge>git commit -m "a.txt, windows eol style"
C:HOMEWAREgit	est	est_merge>git checkout -b windows
Switched to a new branch 'windows'
C:HOMEWAREgit	est	est_merge>echo a3 >> a.txt & echo a4 >> a.txt
C:HOMEWAREgit	est	est_merge>git add a.txt
C:HOMEWAREgit	est	est_merge>git commit -m "add two lines, windows eol style"
C:HOMEWAREgit	est	est_merge>git checkout master
C:HOMEWAREgit	est	est_merge>git checkout -b unix
Switched to a new branch 'unix'
C:HOMEWAREgit	est	est_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt
C:HOMEWAREgit	est	est_merge>dos2unix a.txt
Dos2Unix: Processing file a.txt ...
C:HOMEWAREgit	est	est_merge>git add a.txt
C:HOMEWAREgit	est	est_merge>git commit -m "add 3 lines, all file unix eol style"
[unix c433a63] add 3 lines, all file unix eol style

C:HOMEWAREgit	est	est_merge>git merge windows
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

C:HOMEWAREgit	est	est_merge>git ls-files -u
100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1       a.txt
100644 28b3d018872c08b0696764118b76dd3d0b448fca 2       a.txt
100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3       a.txt

C:HOMEWAREgit	est	est_merge>git mergetool
Merging the files: a.txt

Normal merge conflict for 'a.txt':
  {local}: modified
  {remote}: modified
Hit return to start merge resolution tool (diffmerge):

At this point (Hitting "return"), DiffMerge or KDiff3 will open, and you will see for yourself what lines are actually merged, and what lines are ignored.

Warning: the result file will always be in Windows eol mode (CRLF) with DiffMerge...
KDiff3 offers to save in one way or another.

这篇关于git-merge 是否可以忽略行尾差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆