git - 合并后 Diff 选项卡中的类别是什么
问题描述
我将一个分支合并到另一个分支,在 Diff 选项卡中包含三个包含文件的类别:
与:origin/branch @hash1的差异
与:origin/working_branch @hash2 的
组合 差异
每个类别中有哪些文件?我将 origin/working_branch 合并到 origin/branch。
是这样吗?
Diff with:origin/branch @hash1 - 包含在 origin/working_branch 中更改的文件
Diff with:origin/working_branch @hash2 - 包含在 origin/branch
中更改的文件 Combined Diff - 包含在两个分支中更改的文件
解决方案
其中一些问题是关于Git Extensions的,即图形用户界面。我没有使用它,也无法回答任何关于它的问题。不过,这个问题的另一部分是这些差异的含义/显示,这是基本的命令行 Git。
请记住, Git 中的每个提交都包含您所有文件的完整快照。对于常规(非合并)提交,很容易看到它是如何工作的。每个提交都有一个父提交,因此提交一个接一个地串在一起,我们可以画出一行:
...---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
一样,但足够接近)。
要查看提交,我们可以将其签出,这样我们就可以在工作树中查看所有文件;或者我们可以要求 Git通过将提交与其父级进行比较来显示提交。要查看 commit H
,在 的一角master
,我们让 Git 提取G
和 H
到一个临时区域(在内存中)并比较它们。
中的某些文件G
与H
. Git 对这些文件只字未提。有些文件不匹配;对于这些,Git 向我们展示了一个配方——一个差异列表——我们可以通过它更改文件,G
以便它与.H
合并提交有多个父级。当用较新的提交来绘制它们时,就像我通常在 StackOverflow 上所做的那样,我们会得到这样的结果:
I--J
/ \
...--G--H M--N--...
\ /
K--L
提交M
是一个合并,与父母J
和L
.
合并就像任何其他提交一样:它拥有完整的快照,而不是一组更改。但是我们可以通过将快照与快照进行比较来将其视为更改:M
J
git diff <hash-of-J> <hash-of-M>
例如,正是这样做的。
我们还可以通过比较L
vs将其视为更改M
:
git diff <hash-of-L> <hash-of-M>
任何一个差异都会显示变化。但是,它们将显示的变化是不同的。
因为M
是合并提交,所以当查看J
-vs-时,我们将看到M
的是我们从底行完成的工作中引入的更改,在提交K
和L
. 如果我们比较L
-vs- ,我们将看到我们从顶M
行所做的工作中带来的变化,在提交和. 请注意,例如,它可能是 的精选,因此工作被重复。在这种情况下,合并只获取了这些更改的一个副本,而不是两个副本,因此我们不会在这两个差异中看到这一点。I
J
L
I
组合差异完全是另一回事。在我看来,这是一种有用的尝试,但并不像人们想象的那么成功。Git 组合 diff 所做的是,首先运行每个单独的 diff(在本例中J
为 vsM
和L
vs ) M
,然后从该 diff 中丢弃其他 diff 中根本没有更改的任何文件。
也就是说,假设在 中H
,我们有四个文件,所有这些文件也在I
、J
、K
、L
、 和M
中,并且这些属性具有:
same.txt
在所有六个提交中都是相同的。top-only.txt
I
在和/或中被修改J
,但在K
和/或中不被修改L
。bot-only.txt
K
在和/或中被修改L
,但在I
和/或中不被修改J
。both.txt
J
在和 中被修改L
。
我们还将假设这M
不是一个邪恶的合并(参见Evil merges in git?)。也就是说,H
-vs- M
,如果我们运行该差异,将不会显示任何不是通过I
、J
、K
或获得的更改L
。此外,我们将假设对 的更改both.txt
根本没有重叠,因此合并合并了两个更改:没有冲突,没有其他问题。
显然,diffing J
vsM
没有显示任何内容same.txt
:在之后的五个提交中没有任何一个涉及它H
。
差异J
vsM
不显示 top-only.txt
,因为 inM
中的副本与 中的副本匹配J
。此文件的更改发生在I
和/或J
中,即H
与J
显示更改进行比较,但是对 的H
版本的更改top-only.txt
,导致 的J
版本top-only.txt
,将应用于H
版本以获取M
版本。
由于相同的原因,差异L
vsM
没有显示。 bot-only.txt
同样,M
副本与副本bot-only.txt
匹配L
。
只有和both.txt
之间有区别J
和M
和之间有区别。L
M
如果我们要求 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):这不打印任何内容。git diff -c
(注意一个破折号和一个c
):这显示了both.txt
.
--cc
一个实际上是有道理的。这里的想法是向您展示发生合并冲突的位置。由于没有合并冲突,因此它不显示任何内容。(对于确实显示某些内容的情况,请参阅文档的组合差异格式部分git diff
。)
一个-c
也很有意义,除了一件事:它没有显示给你top-only.txt
,也不显示bot-only.txt
。我们在这里真正需要但 Git 没有的是一种将合并结果快照与合并基础快照进行比较的方法。也就是说,我们可能想查看H
vs 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
)。这基本上从指定合并(或默认)的父级中找到合并基础HEAD
,然后运行所需的差异。
Git 也有-m
选项,可用于git show
两者git log
。该标志有效地将合并“拆分”为单独的“虚拟提交”。每一个都是单亲提交,其单亲是实际合并中的父母之一。然后,Git 的内部差异引擎可以很好地将提交作为普通差异进行差异化,以向您显示它更改了哪些文件。
那么,在这种情况下,git show -m <hash-of-M>
将首先区分J
-vs- M
,然后L
是 -vs- M
,然后向您显示两个差异。
看起来 Git Extensions 没有该-m
选项,但可以选择显示J
-vs- M
diff 或L
-vs- M
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=$1
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 $1";;
esac
git diff $1 $hash
推荐阅读
- language-agnostic - 键入命令并立即执行的工作模式的名称
- mysql - 执行查询时出现错误 2003 Mysql 或错误代码:2013 在查询期间丢失与 MySQL 服务器的连接
- python - 如何将对象转换为可迭代(列表)?
- xml - XSL 中每个循环的条件 XSL
- react-admin - 如何编辑/创建/删除关系/引用 [react-admin]
- php - 如何使用codeigniter从单列中获取数组数据
- here-api - HERE WSE:FindPickup 需要可选的“end”参数?
- node.js - 多对象json数据的招摇响应
- android - 对齐 AppBar 中的收藏按钮
- python - AWS SNS 记录是否始终是单个元素列表?