Hmn*_*shu 6 git merge newline core.autocrlf
Git 自动合并问题:
当在两个不同的分支文件中提交相同的代码时,其中一个分支代码在开始时具有额外的 CRLF/LF。合并时自动合并文件会创建重复项而不会产生任何冲突。请尽早告知。
下图显示了文本文件中所有可能的符号。注意:A 分支没有换行(行:245)。下面的自动合并会创建重复项而不会显示冲突。
(注意:行结尾不是这里的罪魁祸首。)
这个案例很有趣。问题似乎是,无论如何,在 git 的算法中,两组添加的行是在两个不同的位置添加的。Git 不了解代码,只是简单地决定,由于这两个(有些不同)更改将行添加到原始代码的不同部分,因此只需添加这两个不同的更改就可以了。
您应该从中吸取的教训之一是 git 并不聪明。它只是遵循一系列通常有效的简单规则,但仅仅因为它认为成功合并了两组差异,并不意味着结果是正确的。 例如,这也是自动化测试是个好主意的另一个原因。
注意:通过脚本重新创建问题的完整步骤显示在本答案的底部。
让我们在要求 git 合并之前看一下 BranchA 和 BranchB 的状态。关键部分是当我们将git diff合并基础(在此特定设置中的分支的尖端common)与两个实际的尖端提交进行比较时,我们会得到什么。为了查看这些差异,我使用三点形式git diff:
$ git diff BranchB...BranchA
diff --git a/demo-file b/demo-file
index 1d822d4..d222dc7 100644
--- a/demo-file
+++ b/demo-file
@@ -11,6 +11,8 @@ Note that CR-LF is not an issue
get { return valueForKey<int?>("realPortNum") ; }
set { takeValueForKey("realPortNum", value); }
}
+ // ADSO-3530
+ public Decimal? tradeItemDryPhyWetQty
public string riskMktCode
{
$ git diff BranchA...BranchB
diff --git a/demo-file b/demo-file
index 1d822d4..52802fa 100644
--- a/demo-file
+++ b/demo-file
@@ -12,6 +12,9 @@ Note that CR-LF is not an issue
set { takeValueForKey("realPortNum", value); }
}
+ //ADSO-3530
+ public Decimal? tradeItemDryPhyWetQty
+
public string riskMktCode
{
get { return valueForKey<string>("riskMktCode") ; }
$
Run Code Online (Sandbox Code Playgroud)
第一个命令git diff BranchB...BranchA告诉 git:
BranchB查找由和标识的提交BranchA。BranchB(这些分别是和上的两个最尖端的提交BranchA。在这种情况下,它们也是这两个分支上尚未在公共分支上的唯一BranchA提交,因为我们仅在和 上进行了一次独占提交。BranchB在许多实际情况下,一个分支上可能有 10、20 或更多提交,而另一个分支上可能有 2、5、甚至 50 或更多提交,但 git 只找到两个最尖端的提交,用于此步骤.)
找到这两个提交的合并基础。合并基地是历史上两个分支重新汇合的地方。在这种情况下,合并基础非常明显:它是分支顶端的提交common,这是两个分支BranchA和BranchB作为单独分支出现的地方。顶部的提交common位于所有三个分支(以及任何其他分支,例如默认master分支)。
将合并基础与第二次提交进行比较,即BranchA.
第二个命令 的git diff BranchA...BranchB工作原理非常相似。唯一的变化是两个输入提交是按其他顺序选择的。Git 找到相同的合并基础,但现在将提交与 的提示提交进行比较BranchB。
再看一下上面引用的差异。有两种不同的 diff 结果。
第一个 diff 显示 git 应该修改从第 11 行 context 开始的块。 context 的“上方”有三行(第 11、12 和 13 行,这些是 get、set 和闭括号行),然后我们添加了注释和函数声明行,然后有三行“下面”上下文。
第二个差异显示 git 应在从第 12 行(而不是第 11 行)开始的块中添加三行文本。上下文的“上方”三行是设置行、右大括号行和空白行,这些行本身不会被第一个差异更改(尽管它们之间会插入一些文本)。然后我们添加了三行(注释、函数声明和空行),然后我们就有了尾随上下文。
请注意,git 已确定我们新添加的初始空行已经存在,并且我们添加了一个后续空行,并且我们的添加发生在第 14 行,而不是第 13 行 。这解释了为什么这两个添加不冲突:就 git 而言,BranchA更改是“在第 11+3 行添加两行”,更改BranchB是“在 old-line-12+3 处添加三行(添加两行后现在是第 14+3 行)”。
结果是 git添加了两个文本块,尽管它们非常相似。
#! /bin/sh
tdir=/tmp/mergetest
die() {
echo "fatal: $@" 1>&2
exit 1
}
set -e
[ -d $tdir ] && die "$tdir: already exists -- hint: rm -rf $tdir"
mkdir $tdir
cd $tdir
git init
echo "This repository is for demonstrating git merge." > README
git add README
git commit -m initial
# Create common file on common branch.
git checkout -b common
cat << END > demo-file
This is a demo file,
meant to illustrate how git merge works,
why git merge is not very bright,
and why it is therefore necessary to INSPECT THE MERGE RESULTS
(automated tests are good).
The next few lines are not line 241 through 250 here,
but do match the original sample input.
Note that CR-LF is not an issue
(this host Unix-ish system uses simple newlines).
{
get { return valueForKey<int?>("realPortNum") ; }
set { takeValueForKey("realPortNum", value); }
}
public string riskMktCode
{
get { return valueForKey<string>("riskMktCode") ; }
set {
takeValueForKey("riskMktCode", value);
Finally, we have some
trailing text so as to provide
plenty of context area for git,
when it is doing its comparisons of the
merge-base version of the file
against the two branch versions.
END
git add demo-file
git commit -m 'create common base'
# Set variable to two-line form that we will add to both files.
samepart=" // ADSO-3530
public Decimal? tradeItemDryPhyWetQty"
# Make version on BranchA with two added lines.
git checkout -b BranchA
ed - demo-file << END
13a
$samepart
.
w
q
END
git add demo-file
git commit -m 'branch A: add declaration for tradeItemDryPhyWetQty'
# Make alternate version on BranchB with three added lines;
# note that we start from the common base.
git checkout -b BranchB common
ed - demo-file << END
13a
$samepart
.
w
q
END
git add demo-file
git commit -m 'branch B: add declaration for tradeItemDryPhyWetQty'
# Show which commit is the merge-base.
mergebase=$(git merge-base BranchA BranchB)
echo "The merge base is commit $(git rev-parse --short $mergebase)".
# View diffs. Could use "git diff $mergebase BranchA" here.
echo "Here is what we added in BranchA, vs the common base:"
git diff BranchB...BranchA
# Could use "git diff $mergebase BranchB" here.
echo "And, here is what we added in BranchB, vs the common base:"
git diff BranchA...BranchB
echo "Now we merge the two (on BranchA in this case)"
git checkout BranchA
git merge --no-edit BranchB
echo "Comparing the result to the merge base, we get:"
git diff $mergebase HEAD
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2108 次 |
| 最近记录: |