合并后差异选项卡中的类别是什么
What are categories in Diff tab after merge
我将一个分支合并到另一个分支,差异选项卡中包含三个类别的文件:
Diff with: origin/branch @hash1
Diff with: origin/working_branch @hash2
Combined Diff
每个类别中有哪些文件?我将 origin/working_branch 合并到 origin/branch。
是这样的吗?
差异:origin/branch @hash1 - 包含在 origin/working_branch
中更改的文件
差异:origin/working_branch @hash2 - 包含在 origin/branch
中更改的文件
组合差异 - 包含在两个分支中更改的文件
这个问题中有一部分是关于 Git Extensions 图形用户界面的。我没有使用过,也无法回答任何问题。不过,这个问题的另一部分是这些差异的含义/显示,这是基本的 command-line Git.
请记住,在 Git 中的每个 提交都包含所有文件的完整快照。对于常规 (non-merge) 提交,很容易看出它是如何工作的。每个提交都有一个 parent 提交,因此提交是 st运行g,一个接一个,在一条我们可以画的线上:
...---F--G--H <-- master
或:
* 9fadedd637 (master) a commit message subject
|
* 3bab5d5625 some other commit message subject
|
* 1c56d6f57a this commit does something or other
|
:
如 git log --graph
所示(上面的输出是模拟的,与 --graph
所显示的不完全相同,但足够接近)。
要查看一个提交,我们可以检查它,这样我们就有所有个文件在work-tree 我们在哪里可以看到它们;或者我们可以要求 Git 通过将其与 parent 进行比较来 显示 提交。要查看提交 H
,在 master
的末尾,我们 Git 将 G
和 H
提取到一个临时区域(在内存中)和比较它们。
G
中的某些文件与 H
中的对应文件相匹配。 Git 对这些文件只字不提。有些文件 不 匹配;对于那些,Git 向我们展示了一个配方——一个差异列表——通过它我们可以 更改 G
中的文件,以便它 匹配 H
.
中的副本
合并提交有多个 parent。当用较新的提交向右绘制它们时,就像我通常在 Whosebug 上做的那样,我们得到这样的东西:
I--J
/ \
...--G--H M--N--...
\ /
K--L
提交 M
是一个合并,与 parents J
和 L
.
合并就像任何其他提交一样:它包含一个完整的快照,而不是一些更改集。但是我们可以查看它as变化,通过比较M
中的快照和J
中的快照:
git diff <hash-of-J> <hash-of-M>
例如,正是这样做的。
我们还可以通过比较 L
与 M
:
来将其视为变化
git diff <hash-of-L> <hash-of-M>
任何一个 diff 都会显示 变化 。不过,它们显示的变化是不同的。
由于 M
是一个合并提交,在查看 J
-vs-M
时,我们将看到的是我们从一起完成的工作中带来的变化底部 行,在提交 K
和 L
中。如果我们比较 L
-vs-M
,我们将看到我们从 top 行所做的工作带来的变化,在提交 I
和 J
。请注意,例如,L
可能是 I
的 cherry-pick,因此工作是重复的。在这种情况下,合并仅采用这些更改的 一个副本,而不是两个副本,因此我们不会在[=216=中看到]这两个差异中的任何一个。
A combined diff 完全是另一回事。在我看来,这是一种有用的尝试,但并不像人们希望的那样成功。 Git 组合差异首先是 运行 每个单独的差异——在这种情况下,J
vs M
和 L
vs M
—然后 从这个 diff 中删除 任何 not 在另一个 diff 中完全没有改变的文件。
也就是说,假设在H
中,我们有四个文件,都在I
、J
、K
、[=29=中],和 M
,这些属性成立:
same.txt
在所有六个提交中都是相同的。
top-only.txt
在 I
and/or J
中被修改,但在 K
and/or L
中没有修改。
bot-only.txt
在 K
and/or L
中被修改,但在 I
and/or J
中没有修改。
both.txt
在 J
和 L
中被修改。
我们还将假设 M
不是恶意合并(参见 Evil merges in git?)。也就是说,H
-vs-M
,如果我们运行那个差异,不会显示任何未通过[=41获得的变化=]、J
、K
或 L
。此外,我们假设对 both.txt
的更改根本没有重叠,因此合并合并了两个更改:没有冲突,没有其他问题。
显然,J
与 M
的差异显示 same.txt
没有任何意义:在 H
.[=154 之后的五次提交中都没有触及它=]
比较 J
与 M
不显示 top-only.txt
因为 M
中的副本与 J
。此文件的更改发生在 I
and/or J
中,即比较 H
与 J
显示更改,但这些更改对 H
版本top-only.txt
的 J
版本应用于 H
版本以获得 M
版本。
差异 L
与 M
不显示 bot-only.txt
出于同样的原因。同样,bot-only.txt
的 M
副本与 L
副本匹配。
只有both.txt
有J
和M
的区别和L
和[=27=的区别].
如果w向 Git 询问 组合差异 视图 M
,Git 现在将:
- diff
J
vs M
:改变了两个文件:top-only.txt
和both.txt
;和
- diff
L
vs M
:更改了两个文件:bot-only.txt
和 both.txt
.
因此列表更改了三个文件,一个在两个差异中,一个在每个差异中。合并的 diff 现在 丢弃了 only-in-one-diff 个文件,只留下一个文件 both.txt
.
此时,您可以选择两种不同的组合差异:
git diff --cc
(默认值:注意两个破折号和两个 c
s):这会打印 nothing.
git diff -c
(注意一个破折号和一个 c
):这显示了 both.txt
. 的差异
--cc
一个实际上是有道理的。这里的想法是向您展示 合并冲突 的位置。由于 没有 合并冲突,因此它不显示任何内容。 (对于它确实显示某些内容的情况,请参阅 the combined diff format section of the git diff
documentation。)
-c
也有道理,除了一件事:它不会显示 top-only.txt
,也不会显示 bot-only.txt
。我们真正需要的,但 Git 没有,是一种将 merge result 快照与 merge base 快照进行比较的方法.也就是说,我们可能希望查看 H
与 M
。尽管我认为可能应该有,但没有内置操作可以做到这一点。
来自 git show -c
的输出,其中 运行 这种组合差异,在我在这里创建的测试存储库中,是:
commit 54627dbf51ab9b27c8e5486e4755651688dd5d21 (HEAD -> merge)
Merge: da92a96 e77c224
[snip]
diff --combined both.txt
index 5d51eed,506867f..1f3f391
--- a/both.txt
+++ b/both.txt
@@@ -2,10 -2,10 +2,11 @@@ this fil
will be
modified in
both branches.
+here is the top-branch change
The changes
will be
combined into
one file
in the merge result.
+ here is the bottom-branch change
我们可以手动完成。请参阅下面的脚本(命名为 git-show-merge
,因此我可以将其 运行 设为 git show-merge
)。这基本上从指定合并的 parent 中找到合并基础(或 HEAD
作为默认值),然后 运行s 所需的差异。
Git 也有 -m
选项,可用于 git show
和 git log
两者。此标志有效地 "splits" 合并为单独的 "virtual commits"。每个都是一个 single-parent 提交,其单个 parent 是来自实际合并的 parent 之一。 Git 的内部差异引擎与 diff-ing 一样好,它作为普通差异提交,向您显示它更改了哪些文件。
在这种情况下,那么,git show -m <hash-of-M>
将首先区分 J
-vs-M
,然后 L
-vs-M
,然后向您展示两者的差异。
看起来 Git 扩展没有 -m
选项,但可以选择显示 J
-vs-M
差异,或者L
-vs-M
差异,或者——如果你 select 它——combined-diff 格式之一,可能是 --cc
变体。
请注意 git log -p
默认甚至不 尝试 显示合并。使用显式 -c
或 --cc
选项强制 git log
显示组合差异。
#! /bin/sh
USAGE="[commit] the merge commit to show - default is HEAD"
. git-sh-setup
case $# in
0) set HEAD;;
1) ;;
*) usage;;
esac
commit=
hash=$(git rev-parse ${commit}^{commit}) || exit
set -- $(git rev-parse $hash^@)
[ $# -ge 2 ] || die "$commit ($hash) is not a merge"
set -- $(git merge-base --all $@)
case $# in
0) die "parents of ${commit} are unrelated";;
1) ;;
*) echo "warning: more than one merge base, diffing against ";;
esac
git diff $hash
我将一个分支合并到另一个分支,差异选项卡中包含三个类别的文件:
Diff with: origin/branch @hash1
Diff with: origin/working_branch @hash2
Combined Diff
每个类别中有哪些文件?我将 origin/working_branch 合并到 origin/branch。
是这样的吗?
差异:origin/branch @hash1 - 包含在 origin/working_branch
中更改的文件
差异:origin/working_branch @hash2 - 包含在 origin/branch
中更改的文件
组合差异 - 包含在两个分支中更改的文件
这个问题中有一部分是关于 Git Extensions 图形用户界面的。我没有使用过,也无法回答任何问题。不过,这个问题的另一部分是这些差异的含义/显示,这是基本的 command-line Git.
请记住,在 Git 中的每个 提交都包含所有文件的完整快照。对于常规 (non-merge) 提交,很容易看出它是如何工作的。每个提交都有一个 parent 提交,因此提交是 st运行g,一个接一个,在一条我们可以画的线上:
...---F--G--H <-- master
或:
* 9fadedd637 (master) a commit message subject
|
* 3bab5d5625 some other commit message subject
|
* 1c56d6f57a this commit does something or other
|
:
如 git log --graph
所示(上面的输出是模拟的,与 --graph
所显示的不完全相同,但足够接近)。
要查看一个提交,我们可以检查它,这样我们就有所有个文件在work-tree 我们在哪里可以看到它们;或者我们可以要求 Git 通过将其与 parent 进行比较来 显示 提交。要查看提交 H
,在 master
的末尾,我们 Git 将 G
和 H
提取到一个临时区域(在内存中)和比较它们。
G
中的某些文件与 H
中的对应文件相匹配。 Git 对这些文件只字不提。有些文件 不 匹配;对于那些,Git 向我们展示了一个配方——一个差异列表——通过它我们可以 更改 G
中的文件,以便它 匹配 H
.
合并提交有多个 parent。当用较新的提交向右绘制它们时,就像我通常在 Whosebug 上做的那样,我们得到这样的东西:
I--J
/ \
...--G--H M--N--...
\ /
K--L
提交 M
是一个合并,与 parents J
和 L
.
合并就像任何其他提交一样:它包含一个完整的快照,而不是一些更改集。但是我们可以查看它as变化,通过比较M
中的快照和J
中的快照:
git diff <hash-of-J> <hash-of-M>
例如,正是这样做的。
我们还可以通过比较 L
与 M
:
git diff <hash-of-L> <hash-of-M>
任何一个 diff 都会显示 变化 。不过,它们显示的变化是不同的。
由于 M
是一个合并提交,在查看 J
-vs-M
时,我们将看到的是我们从一起完成的工作中带来的变化底部 行,在提交 K
和 L
中。如果我们比较 L
-vs-M
,我们将看到我们从 top 行所做的工作带来的变化,在提交 I
和 J
。请注意,例如,L
可能是 I
的 cherry-pick,因此工作是重复的。在这种情况下,合并仅采用这些更改的 一个副本,而不是两个副本,因此我们不会在[=216=中看到]这两个差异中的任何一个。
A combined diff 完全是另一回事。在我看来,这是一种有用的尝试,但并不像人们希望的那样成功。 Git 组合差异首先是 运行 每个单独的差异——在这种情况下,J
vs M
和 L
vs M
—然后 从这个 diff 中删除 任何 not 在另一个 diff 中完全没有改变的文件。
也就是说,假设在H
中,我们有四个文件,都在I
、J
、K
、[=29=中],和 M
,这些属性成立:
same.txt
在所有六个提交中都是相同的。top-only.txt
在I
and/orJ
中被修改,但在K
and/orL
中没有修改。bot-only.txt
在K
and/orL
中被修改,但在I
and/orJ
中没有修改。both.txt
在J
和L
中被修改。
我们还将假设 M
不是恶意合并(参见 Evil merges in git?)。也就是说,H
-vs-M
,如果我们运行那个差异,不会显示任何未通过[=41获得的变化=]、J
、K
或 L
。此外,我们假设对 both.txt
的更改根本没有重叠,因此合并合并了两个更改:没有冲突,没有其他问题。
显然,J
与 M
的差异显示 same.txt
没有任何意义:在 H
.[=154 之后的五次提交中都没有触及它=]
比较 J
与 M
不显示 top-only.txt
因为 M
中的副本与 J
。此文件的更改发生在 I
and/or J
中,即比较 H
与 J
显示更改,但这些更改对 H
版本top-only.txt
的 J
版本应用于 H
版本以获得 M
版本。
差异 L
与 M
不显示 bot-only.txt
出于同样的原因。同样,bot-only.txt
的 M
副本与 L
副本匹配。
只有both.txt
有J
和M
的区别和L
和[=27=的区别].
如果w向 Git 询问 组合差异 视图 M
,Git 现在将:
- diff
J
vsM
:改变了两个文件:top-only.txt
和both.txt
;和 - diff
L
vsM
:更改了两个文件:bot-only.txt
和both.txt
.
因此列表更改了三个文件,一个在两个差异中,一个在每个差异中。合并的 diff 现在 丢弃了 only-in-one-diff 个文件,只留下一个文件 both.txt
.
此时,您可以选择两种不同的组合差异:
git diff --cc
(默认值:注意两个破折号和两个c
s):这会打印 nothing.git diff -c
(注意一个破折号和一个c
):这显示了both.txt
. 的差异
--cc
一个实际上是有道理的。这里的想法是向您展示 合并冲突 的位置。由于 没有 合并冲突,因此它不显示任何内容。 (对于它确实显示某些内容的情况,请参阅 the combined diff format section of the git diff
documentation。)
-c
也有道理,除了一件事:它不会显示 top-only.txt
,也不会显示 bot-only.txt
。我们真正需要的,但 Git 没有,是一种将 merge result 快照与 merge base 快照进行比较的方法.也就是说,我们可能希望查看 H
与 M
。尽管我认为可能应该有,但没有内置操作可以做到这一点。
来自 git show -c
的输出,其中 运行 这种组合差异,在我在这里创建的测试存储库中,是:
commit 54627dbf51ab9b27c8e5486e4755651688dd5d21 (HEAD -> merge)
Merge: da92a96 e77c224
[snip]
diff --combined both.txt
index 5d51eed,506867f..1f3f391
--- a/both.txt
+++ b/both.txt
@@@ -2,10 -2,10 +2,11 @@@ this fil
will be
modified in
both branches.
+here is the top-branch change
The changes
will be
combined into
one file
in the merge result.
+ here is the bottom-branch change
我们可以手动完成。请参阅下面的脚本(命名为 git-show-merge
,因此我可以将其 运行 设为 git show-merge
)。这基本上从指定合并的 parent 中找到合并基础(或 HEAD
作为默认值),然后 运行s 所需的差异。
Git 也有 -m
选项,可用于 git show
和 git log
两者。此标志有效地 "splits" 合并为单独的 "virtual commits"。每个都是一个 single-parent 提交,其单个 parent 是来自实际合并的 parent 之一。 Git 的内部差异引擎与 diff-ing 一样好,它作为普通差异提交,向您显示它更改了哪些文件。
在这种情况下,那么,git show -m <hash-of-M>
将首先区分 J
-vs-M
,然后 L
-vs-M
,然后向您展示两者的差异。
看起来 Git 扩展没有 -m
选项,但可以选择显示 J
-vs-M
差异,或者L
-vs-M
差异,或者——如果你 select 它——combined-diff 格式之一,可能是 --cc
变体。
请注意 git log -p
默认甚至不 尝试 显示合并。使用显式 -c
或 --cc
选项强制 git log
显示组合差异。
#! /bin/sh
USAGE="[commit] the merge commit to show - default is HEAD"
. git-sh-setup
case $# in
0) set HEAD;;
1) ;;
*) usage;;
esac
commit=
hash=$(git rev-parse ${commit}^{commit}) || exit
set -- $(git rev-parse $hash^@)
[ $# -ge 2 ] || die "$commit ($hash) is not a merge"
set -- $(git merge-base --all $@)
case $# in
0) die "parents of ${commit} are unrelated";;
1) ;;
*) echo "warning: more than one merge base, diffing against ";;
esac
git diff $hash