哪个Git命令会显示仅存在于分支中已完全合并到主分支的提交内容?

4
哪些Git命令可以显示仅存在于已完全合并到master的分支中的内容?有些内容可能在master中丢失,例如某些合并操作可能使用了ours策略,忽略了分支内容(即git merge --strategy ours branch)。
我发现通常的Git比较操作不能产生我所需的结果。
例如,命令git diff master..branchgit diff branch..master无法工作,因为这些命令显示了master中存在的内容差异。(如何修改此命令以省略master上的更改?)
命令git diff master...branch也无法工作,因为所有branch上的提交都曾在多个合并操作中被合并到master中。
示例:
  1. 在分支master中创建文件a.txt
  2. 在分支master中添加第1行到a.txt
  3. 创建分支branch
  4. 在分支branch中添加第2行到a.txt
  5. 切换到分支master
  6. 在分支master中添加第2行到a.txt
  7. 使用策略ours将分支branch合并到master。这类似于一个“虚拟”合并,将branch上的所有提交合并到master,但丢弃其内容。
  8. 比较分支masterbranch
命令序列:
derek@derek-lubuntu:~/Projects$ git init test
Initialized empty Git repository in /home/derek/Projects/test/.git/
derek@derek-lubuntu:~/Projects$ cd test
derek@derek-lubuntu:~/Projects/test$ touch a.txt
derek@derek-lubuntu:~/Projects/test$ git add a.txt
derek@derek-lubuntu:~/Projects/test$ git commit --message "Added a.txt."
[master (root-commit) 6a36816] Added a.txt.
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
derek@derek-lubuntu:~/Projects/test$ echo "Line 1 from master." >> a.txt
derek@derek-lubuntu:~/Projects/test$ git commit -a --message "Added line 1."
[master c9ebf16] Added line 1.
 1 file changed, 1 insertion(+)
derek@derek-lubuntu:~/Projects/test$ git checkout -b branch
Switched to a new branch 'branch'
derek@derek-lubuntu:~/Projects/test$ echo "Line 2 from branch." >> a.txt
derek@derek-lubuntu:~/Projects/test$ git commit -a --message "Added line 2."
[branch 8a142dd] Added line 2.
 1 file changed, 1 insertion(+)
derek@derek-lubuntu:~/Projects/test$ cat a.txt
Line 1 from master.
Line 2 from branch.
derek@derek-lubuntu:~/Projects/test$ git checkout master
Switched to branch 'master'
derek@derek-lubuntu:~/Projects/test$ echo "Line 2 from master." >> a.txt
derek@derek-lubuntu:~/Projects/test$ git commit -a --message "Added line 2."
[master d496cc7] Added line 2.
 1 file changed, 1 insertion(+)
derek@derek-lubuntu:~/Projects/test$ git merge --strategy ours branch
Merge made by the 'ours' strategy.
derek@derek-lubuntu:~/Projects/test$ git merge branch
Already up-to-date.
derek@derek-lubuntu:~/Projects/test$ git diff master..branch
diff --git a/a.txt b/a.txt
index f773e76..5dae91a 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,2 @@
 Line 1 from master.
-Line 2 from master.
+Line 2 from branch.
derek@derek-lubuntu:~/Projects/test$ git diff branch..master
diff --git a/a.txt b/a.txt
index 5dae91a..f773e76 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,2 @@
 Line 1 from master.
-Line 2 from branch.
+Line 2 from master.
derek@derek-lubuntu:~/Projects/test$ git diff master...branch
derek@derek-lubuntu:~/Projects/test$ git diff branch...master
diff --git a/a.txt b/a.txt
index 5dae91a..f773e76 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,2 @@
 Line 1 from master.
-Line 2 from branch.
+Line 2 from master.

我可以使用哪个Git操作来仅显示“+来自分支的第二行。”而忽略“+来自主分支的第二行。”或“-来自主分支的第二行。”?

你尝试过使用 git diff master branch 吗? - neshkeev
这不就和 git diff master..branch 一模一样吗? - Derek Mahar
@zaratustra 我认为 OP 希望该命令忽略 master 中不在 branch 中的添加。git diff master branch 会显示双向添加/删除(我不知道有任何不会这样做的差异工具)。 - SnoringFrog
@zaratustra,我在我的问题中添加了一个示例以说明我的问题。 - Derek Mahar
@SnoringFrog,是的,你正确理解了我的问题。 - Derek Mahar
显示剩余2条评论
2个回答

0

如何在Linux中进行单向差异比较?中得到启发:

您可以将diff的输出导入grep以筛选出主分支中存在的更改。我知道的最好方法是忽略任何以连字符开头的行。

git diff master branch | grep -v "^-"

对我来说,在按照您的步骤操作后,这显示了以下输出:

diff --git a/a.txt b/a.txt

index f908dc1..1b5b3bd 100644

+++ b/a.txt

@@ -1,2 +1,2 @@

this line in both files

+line2 on branch

git diff master branch则显示

diff --git a/a.txt b/a.txt

index f908dc1..1b5b3bd 100644

--- a/a.txt

+++ b/a.txt

@@ -1,2 +1,2 @@

这一行在两个文件中都存在

-主分支中的第二行

+分支中的第二行

这样做的副作用是从差异中去除颜色,并将其直接打印到标准输出而不是到less。由于颜色有助于区分列出的每个更改所在的文件,因此在一个文件的更改被删除时,它不应该是必需的。如果您需要保持在less中显示的内容,请只需在命令末尾添加一个管道符号到less即可。

编辑:正如@DerekMahar在他的评论中指出的那样,这只显示了在branch上的添加,而这些添加在master中没有反映。我不确定如何修改此内容以包括来自branch的所有更改,因为我不知道在查看差异时区分对master的添加和对branch的减少的简单方法。


以下是一个非常粗略的想法,正如在这里所解释的那样,它并不能完全解决问题,但我觉得这已经足够作为一个开始,以防有人知道如何解决它的问题:

我的最佳初步想法(需要比我现在有时间编写更多的脚本,并且还有自己的一系列问题,但我认为我应该把它放在这里,以防有人可以使用它)是获取 git diff master branch | grep "^-" 的输出(注意缺少 -v),然后在 branch 中的正确文件中搜索该输出的行(文件名将在第一行输出中提供)。我们将知道在 branch 中找到的任何行都是从 master 中删除的,而未找到的任何行都是添加到 master 中的。然而,可能重复的行(例如,单独的 {)会很快导致此方法出现问题,我不确定如何解决这个问题。


这可能适用于我所提供的简单示例,但在另一种情况下,它也会有副作用,即省略了“branch”可能已删除的行。它还不会忽略仅添加到“master”的文件。 - Derek Mahar
在这种情况下,我认为你没有什么办法,因为无法区分“从branch中删除”和“添加到master”(即使在查看普通差异时,据我所知,更不用说单向差异了),因为两者都会导致在master中缺少branch的文本。 - SnoringFrog
SnoringFrog,你可能是对的,但算法并不太难。Git需要计算branch上所有更改与它们合并到master时实际产生的更改之间的差异,同时忽略master上的所有新更改。 - Derek Mahar
1
也许这比我最初想象的要难实现。 - Derek Mahar
@DerekMahar 我最好的初始想法(需要比我现在能做的更多的脚本编写工作)是获取所有以“-”开头的差异行,将它们保存起来,然后在 branch 中搜索每一行。任何被发现的都从主分支中删除,任何未被发现的都添加到主分支中。你需要考虑如何重新格式化和有效地搜索这些行。但必须考虑顺序,否则重复的行将会创建许多问题。 - SnoringFrog

0

应用我在之前评论中提到的算法:

  1. 使用命令git diff $(git merge-base master branch)^ branch 计算 branchmaster 分支出来以来的所有变更。 在给定的示例中,$(git merge-base master branch)^ 是指 branch 上第一次提交的父提交。
  2. 将这些更改传输到 patch -p1 中并将其应用到 master 分支上。
  3. 使用git diff计算差异。

例如:

derek@derek-lubuntu:~/Projects/test$ git diff $(git merge-base master branch)^ branch | patch -p1
patching file a.txt
Hunk #1 succeeded at 1 with fuzz 1.
derek@derek-lubuntu:~/Projects/test$ git diff
diff --git a/a.txt b/a.txt
index f773e76..de87c33 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,3 @@
 Line 1 from master.
+Line 2 from branch.
 Line 2 from master.
derek@derek-lubuntu:~/Projects/test$ 

虽然这不会省略对master应用的更改,但它确实防止git diff将其报告为更改。

请注意,步骤1仅适用于分支仅合并一次的情况,而这不是我的情况。相反,我们可以标记原始分支提交,幸运的是,我已经完成了这个步骤。


当分支被多次合并且存在许多冲突时,这种方法效果不佳。 :( - Derek Mahar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接