git-merge可能会忽略行结束的差异吗?
git merge
可以忽略行结束的差异吗?
也许我在问错误的问题……但是:
我尝试了uisng的config.crlf input
但事情有点乱,失控,特别是当我应用它后,事实 。
首先,在应用此选项之前应用此configuration似乎不会影响提交到存储库的文件。 另一件事是突然所有提交现在导致大量关于CRLF转换为LF的恼人的警告消息。
说实话,我并不在意使用什么行结尾,我个人更喜欢Unix风格\n
,但无论如何。 我所关心的只是让git merge
变得更聪明一些,忽略了行尾的差异。
有时我有两个相同的文件,但git会标记为冲突(冲突是整个文件),只是因为它们使用不同的行结束字符。
更新:
我发现, git diff
接受一个--ignore-space-at-eol
选项,是否可以让git merge
使用这个选项呢?
2013年更新:
更新的git版本授权使用合并策略recursive
和策略选项 ( -X
):
- 从“ Git合并和修复混合空间和两个分支的选项卡 ”:
git merge -srecursion-Xignore-space-at-eol
但是使用“ -Xignore-space-change
” 也是可能的
- Fab-V在下面提到 :
git merge master -srecursion-X重新正常化
jakub.g也评论说,这些策略也适用于樱桃采摘 :
git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize
这比ignore-all-space
要好得多。
原文答复(2009年5月)
忽略eol风格的补丁已经在2007年6月提出,但它只涉及git diff --ignore-space-at-eol
,而不是git merge
。
当时,这个问题已经被提出来了:
应该
--ignore-space-at-eol
是git-merge
的选项吗?
合并是这个function很重要的地方。
什么是自动解决的合并与这些选项有效的语义 – 他们只用于重命名检测,或者,我们,例如,不标志冲突只有空白的变化? 如果我们没有,我们自动接受哪个版本?
Julio C Hamano并不十分热心:
这当然是诱人的,但我怀疑应该留待以后。
我怀疑它会引入两种不同types差异的概念,一种是机械处理(即用于合并“git-merge-recursive”,适用于“git-am”),另一种用于检查人类去了解。
即使比较输出文件的输出可能不容易用于机械应用,对后一种情况的input也是有用的。
git merge
的总体思路是依靠第三方合并工具。
例如,我将DiffMerge设置为Git合并工具,设置一个规则集 ,允许合并工具忽略某些types的文件的eol。
在Windows上安装MSysGit1.6.3,用于DOS或Git bash会话,使用DiffMerge或KDiff3:
- 设置一个目录到你的PATH(这里是:
c:\HOMEWARE\cmd
)。 - 在该目录中添加脚本merge.sh(您最喜爱的合并工具的包装)
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
- 声明Git的合并包装器
Gitconfiguration命令:
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
- 检查autoCRLF是否为false
系统级别的git config:
git config ---system core.autoCRLF=false
- testing一下,当两行是相同的(但他们的eol字符)时,DiffMerge或KDiff3将在合并期间忽略这些行。
DOS脚本(注意: dos2unix命令来自这里 ,用于模拟Unix的eol风格,该命令已经被复制到本答复开头提到的目录中):
C:\HOMEWARE\git\test>mkdir test_merge C:\HOMEWARE\git\test>cd test_merge C:\HOMEWARE\git\test\test_merge>git init C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout -b windows Switched to a new branch 'windows' C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout master C:\HOMEWARE\git\test\test_merge>git checkout -b unix Switched to a new branch 'unix' C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:\HOMEWARE\git\test\test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:\HOMEWARE\git\test\test_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:\HOMEWARE\git\test\test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:\HOMEWARE\git\test\test_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):
此时(点击“返回”),DiffMerge或KDiff3将打开,您将自己看到实际合并的行,以及忽略哪些行。
警告 :结果文件将始终处于Windows eol模式(CRLF)与DiffMerge …
KDiff3提供以这种或那种方式保存。
我正在寻找相同的答案,我发现这一点
合并具有不同签入/签出属性的分支
如果您已经将属性添加到导致该文件的规范存储库格式发生更改的文件(如添加干净/涂抹filter或text / eol / ident属性),那么合并任何属性不在位的任何东西通常会导致合并冲突。
为了防止这些不必要的合并冲突,通过设置merge.renormalizeconfigurationvariables来解决三向合并时,git可以被告知运行虚拟检出和检入文件的所有三个阶段。 这可以防止转换后的文件与未转换的文件合并时由检入转换引起的更改导致虚假合并冲突。
只要“污迹→清理”与“干净”相同,即使对已经被污染的文件也会产生相同的输出,该策略将自动解决所有与过滤相关的冲突。 不以这种方式运行的筛选器可能会导致额外的合并冲突,必须手动解决。
所以在任何仓库中运行这个命令都可以做到这一点:
git config merge.renormalize true
阅读https://stackoverflow.com/a/12194759/1441706和https://stackoverflow.com/a/14195253/1441706后;
对我来说,这个命令完美地实现了这个技巧:
git merge master -s recursive -X renormalize
正如在这个答案: https : //stackoverflow.com/a/5262473/943928
你可以试试: git merge -s recursive -Xignore-space-at-eol
我所做的就是把所有的东西都保存为默认值(例如autocrlf = true),触摸所有文件(find。-exec touch {} \;),让git将它们视为“已修改”并将它们提交回来,然后完成。 否则,你总会被困扰的消息或令人惊讶的差异所困扰,或者不得不closures所有的git的空白function。
你会失去责备的信息,但最好早点做,而不是晚点:)
“git merge -Xrenormalize”就像一个魅力。
这看起来不是可以直接完成的,但是这个post提出了一个解决方法。
http://stahlforce.com/dev/index.php?tool=remcrlf
我试过了,但是如果在你的代码的最后一行之后,你还没有CRLF它自己添加了一个LF,并且这个文件在git中看起来改变了。 除此之外,它的作品。
现在看来,最好的方法是在合并之前对两个分支(和提交)的行结束进行归一化。
我用googlesearch“convert crlf to lf”,发现这是第一个结果:
http://stahlforce.com/dev/index.php?tool=remcrlf
我下载并使用,似乎是一个不错的工具。
>sfk remcr . .py
请确保指定一个目录和一个文件types(例如.py),否则它可能会尝试.git
目录的内容!
AFAICT,(我还没有尝试过),你可以使用git diff
来比较你想合并的分支到共同的祖先,然后用git apply
应用结果。 两个命令都有--ignore-whitespace
选项来忽略行尾和空格错误。
不幸的是,如果修补程序不适用,整个操作就会中止。 您无法修复合并冲突。 有一个--reject
选项可以将不可修改的--reject
保留在.rej
文件中,这有助于,但不同于在一个文件中显示合并冲突。
阅读parsing合并冲突后:强制覆盖所有文件
我终于解决了这个问题的版本。 我试图从上游回购拉动更新,但我目前的一个是有CRLF相关的问题,因此无法合并。 应该指出,我没有本地变化,我需要担心。 以下步骤解决了我的问题:
根据Github关于同步分叉的说明( https://help.github.com/articles/syncing-a-fork/ ):
-
git fetch upstream
-
git reset --hard upstream/master
我对git有限的理解告诉我,这是做我想要的 – 重新分配我的叉(没有实际未提交的变化),以获得对上游源的所有更改。 根据源页面,通常不需要这个步骤,但CRLF问题是必需的。 -
git merge upstream/master
-
git push
但是我build议使用像sed这样的工具来实现正确的行尾,然后diff文件。 我花了几个小时对不同的线路结局进行区分 。
最好的方法是:
- 将只有项目文件(省略
.git
目录)复制到另一个目录中创build存储库,然后添加文件并提交它们(应该在新的存储库中的主分支上)。 - 从第二个项目复制文件到同一个文件夹,但另一个分支例如
dev
(git checkout -b dev
),提交这个分支上的文件并运行(如果第一个项目在master):git diff master..dev --names-only
仅查看已更改文件的名称