合并提交的git显示 [英] git show of a merge commit

查看:106
本文介绍了合并提交的git显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我有一个合并提交并运行git show #commit时,它只显示提交日志,而不是真正改变的差异,比如

  commit c0f50178901e09a1237f7b9d9173ec5d1c4936c 
合并:ed234b ded051
作者:abc
日期:Mon Nov 21 15:56:33 2016 -0800

合并分支'abc'

我明白真正的提交是在合并日志中,但我想保存输入,是有没有办法在一个显示差异?

解决方案

TL;使用 git show -m c05f017 git show --first-parent c05f017 ,或者 git diff c05f017 ^ c05f017






你的问题存在一个基本错误:提交不是差异;提交是快照。这可能看起来像一个没有区别的区别 - 对于某些提交,它是 。但是对于合并提交,它不是


$ b $ < git show (或 git log -p )将一个commit 显示为一个diff,它将的快照与其他内容进行比较。 git diff 命令执行同样的事情:它将一次提交与另一次提交进行比较。 (或者它可以比较一个提交工作树,或索引的内容,或几个其他组合。)



对于普通的提交,它是比较这个提交的快照到前一个(即父代)提交的快照。所以这就是 git show does(和 git log -p ):它运行一个 git diff 从这个提交。



合并提交并不只有一个父提交。它们有两个父母。 1 这就是让他们首先合并提交的原因:合并提交的定义是至少有两个父母的提交。 / p>




1 合并提交可以有三个或更多个父项。这些被称为章鱼合并。不过,他们并没有做任何特别的事情,主要是为了炫耀。 :-)你可以在这里忽略它们。






当有两个父母时,哪一个应该 git show 比较对比



选择默认情况下不做比较。你可以通过添加各种标志来显示某些内容(见下面)。



git show 选择做默认更复杂。由于有两个父母,所以 git show 首先与第一父母进行比较,然后将 2 与第二父母进行比较。然后 - 这部分是非常重要的 - 它结合了两个差异,产生了一个所谓的组合差异。

,让我注意一个棘手的,但非常有用的Git语法。如果您有一个提交ID,例如 c05f017 ,则可以在此之后添加一个插入符号或帽子字符 ^ ,以命名父提交。您可以选择添加另一个数字来选择哪个父项。对于常规(非合并)提交,只有一个提交,所以 c05f017 ^ 父项。对于合并提交, c05f017 ^ c05f017 ^ 1 均表示第一个父,而 c05f017 ^ 2 表示第二个父母




2 我将它放在引号中,因为在Git中,第一个父元素的想法尤其重要,正如我们稍后会看到的。换句话说,Git关心的大部分是第一个,而其余的只是其余。






组合差异



组合差异格式在文档,但首先描述一个关键位 here ,以便使其特别模糊: 3


请注意,组合diff 仅列出所有父母修改过的文件。


也就是说,假设 M 是合并提交,并且diff M ^ 1 vs M em>说文件 mainline.txt common.txt 都改变了。假设进一步的差异 M ^ 2 M 表示文件 sidebranch.txt 常见.txt 都改变了。组合差异将仅显示 common.txt ,同时跳过 mainline.txt sidebranch.txt 因为这两个文件只能从一个父母(每个)修改。 (即使Git可能只显示 common.txt 的一些差异。)






3 我花了很长时间在文档中找到它,因为我一直在看另一部分。






分割差异



-m 选项 - m 在这里可能代表 merge - 告诉Git实际上拆分合并。也就是说,不是试图将每个父级的差异组合到一个大的组合差异中,而是每次父母显示差异值,每次差异一次。



这有时候是你想要的。当它不是你想要的,你可以运行你自己的明确的 git diff 来与两个父母中的一个进行比较(见下文)。

你应该区分哪一个父母?



通常,正确的答案是第一个父母。



第一父概念的关键在于,当Git进行合并提交时,它始终会记录当时所在的分支,作为第一个父代。如果你在 develop 上,并且你合并了<$

c $ c> topic :

  $ git checkout develop 
$ git merge topic

Git将创建一个新的提交 - 一个合并提交在你当前的分支上, develop 。合并提交的第一个父项将是刚才 develop 的提示。 第二个父母将是(仍然)是主题的提示的提交。



<因为你通常关心合并带来什么,所以与第一位父母进行比较会给你。所以通常这就是你想要的。因此, git show 允许您运行 git show --first-parent 。这个分割了提交,然后 git show 仅与第一个父代相比较。 (这与 git show -m 有点不同,它会将提交分裂两次:第一个拆分与第一个父代进行比较,第二个拆分与第二个父代进行比较。 )



同样,您可以运行 git log -p --first-parent ...但您仍然必须添加 -m 以将修改看作一个补丁,因为默认情况下 git log 只是显示完全为合并。 (在内部,由于跳过合并操作会覆盖拆分的方式,而不是合并。)这里, - 第一个父标志具有一个甚至更重要的影响:日志操作根本不会查看任何的分支提交,只有那些在主(第一父)行上。


when I have a merge commit and run git show #commit, it shows only commit log, not the the diff to the real change, like

commit c0f50178901e09a1237f7b9d9173ec5d1c4936c
Merge: ed234b ded051
Author: abc
Date:   Mon Nov 21 15:56:33 2016 -0800

    Merge branch 'abc'

I understand the real commit is in merge log, but I want to save typing, is there a way to show the diff in one?

解决方案

TL;DR: use git show -m c05f017 or git show --first-parent c05f017, or perhaps git diff c05f017^ c05f017.


There's a fundamental error in your question: commits are not diffs; commits are snapshots. This might seem like a distinction without a difference—and for some commits, it is. But for merge commits, it's not.

When git show (or git log -p) shows a commit as a diff, it's doing so by comparing the commit's snapshot to something else. The git diff command does the same thing: it compares one commit to another commit. (Or it can compare a commit to the work-tree, or to the contents of the index, or a few other combinations as well.)

For ordinary commits, it's trivially obvious what to compare: compare this commit's snapshot to the previous (i.e., parent) commit's snapshot. So that is what git show does (and git log -p too): it runs a git diff from the parent commit, to this commit.

Merge commits don't have just one parent commit, though. They have two parents.1 This is what makes them "merge commits" in the first place: the definition of a merge commit is a commit with at least two parents.


1A merge commit can have three or more parents. These are called "octopus merges". They don't do anything special, though, and are mainly for showing off. :-) You can ignore them here.


When there are two parents, which one(s) should git show compare against?

What git log -p chooses to do by default is not to compare at all. You can make it show something by adding various flags (see below).

What git show chooses to do by default is more complicated. Since there are two parents, git show first compares against the "first parent",2 then compares against the second parent. Then—this part is quite crucial—it combines the two diffs, producing a so-called "combined diff".

For the next section, let me note a tricky, but very useful, bit of Git syntax. If you have a commit ID like c05f017, you can add a caret or "hat" character ^ after that, to name a parent commit. You can optionally add another number to select which parent. For regular (non-merge) commits there's only one, so c05f017^ is the parent. For merge commits, c05f017^ and c05f017^1 both mean the first parent, while c05f017^2 means the second parent.


2I put this in quotes because the first parent idea is especially important in Git, as we will see in a moment. In other words, Git cares most about which parent is first, while the rest are just "the rest".


Combined diffs

The combined diff format is described in the documentation, but a key bit is first described here, so as to make it especially obscure:3

Note that combined diff lists only files which were modified from all parents.

That is, suppose M is a merge commit, and diffing M^1 vs M says file mainline.txt and common.txt were both changed. Suppose further that diffing M^2 and M says that file sidebranch.txt and common.txt were both changed. The combined diff will show only common.txt, skipping both mainline.txt and sidebranch.txt because those two files were only modified from one parent (each). (Even then Git may show only some of the diffs for common.txt.)


3It took me a long time to find this in the documentation, as I kept looking at the other section.


Splitting the diffs

The -m option—m probably stands for merge here—tells Git to, in effect, "split" the merge. That is, instead of trying to combine the diffs against each parent into one big combined diff, just show the diff against each parent, one diff at a time.

This is sometimes what you want. When it's not what you want, you can run your own explicit git diff to just diff against one of the two parents (or see below).

Which parent should you diff against?

Usually, the correct answer is "the first parent".

The key to the "first parent" notion is that when Git makes a merge commit, it always records the branch you're on at the time, as the first parent. The other branch becomes the second parent.

That is, if you're on develop and you merge topic:

$ git checkout develop
$ git merge topic

Git will make a new commit—a merge commit, with two parents—on your current branch, develop. The first parent of the merge commit will be the commit that was the tip of develop just a moment ago. The second parent will be the commit that is (still) the tip of topic.

Since you're usually concerned with what the merge brought in, comparing against the first parent will give you that. So usually that's what you want. For this reason, git show allows you to run git show --first-parent. That "splits" the commit and then git show only diffs against the first parent. (This is a bit different than git show -m, which splits the commit twice: the first split compares against the first parent, and the second split compares against the second parent.)

Similarly, you can run git log -p --first-parent ... but you must still add -m to see the change as a patch, because by default git log just skips showing the diffs entirely for a merge. (Internally, the skipping-because-merge operation overrides the way the split makes it act like not-a-merge.) Here, the --first-parent flag has an even more important effect: the log operation does not look at any of the side branch's commits at all, only those on the main (first-parent) line.

这篇关于合并提交的git显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆