如何从master合并后找出分支上的哪些更改?

时间:2016-10-03 17:51:02

标签: git branch diff

我为master分叉了一个分支。我不时将master合并到我的分支中进行更新。

       /--B--D--G--H--J--L--M--> dev (HEAD)
      /        /     /
-----A--C--E--F--I--K---> master

如何仅在我的分支上显示更改,不包括合并中的更改? 即仅在提交BDHLM时显示差异。

git diff A无效,因为它包含来自master的合并更改。

顺便说一下,如果有人知道如何快速查找A而不继续向下滚动日志,我将不胜感激。

1 个答案:

答案 0 :(得分:3)

我不清楚你正在寻找什么。但请注意:

  • 提交商店快照。这意味着提交K具有完整的源树,该树独立于提交ABC等中的任何内容。同样,提交J具有完整的快照,与AK或任何其他提交中的任何内容无关。

    (单词"独立"这里意味着如果你要求Git检索提交J,那么在你做出{K之后设法改变提交J并不重要{1}}。它实际上不是可能来改变任何提交,git commit --amend 似乎来更改提交,但实际上并非如此。 )

  • 在两次特定提交中使用git diff,Git会提取两个快照中的每一个,并对这些快照进行比较。

简单差异

因此,git diff K M将显示master(提交K)的当前提示与dev的当前提示之间的不同之处(提交{{1} }})。

您也可以拼写此M

这可能是你想要看到的(再一次,它对我来说并不是很清楚)。所以回答1:git diff master dev

多个独立差异

另一方面,也许你想要的是为commit git diff master dev展示一个diff,为commit B展示一个diff,为commit D展示一个diff,为commit {展示一个diff。 {1}},以及提交H的一个差异。也就是说,您希望每次看到每个非合并提交,与其(单个)父级相比。

您可以LM,依此类推。但您也可以git diff A Bgit diff B D等等。这会将提交显示为更改,而不是快照。

如果提交存储快照而不是更改,您可能想知道这是如何实现的。 (由于大多数其他版本控制系统确实存储了更改,因此很多人都会参与其中。)这个明显矛盾的答案是git show B查找您绘制的相同图表。

再次查看提交git show D。在它之前发生了什么?也就是说,哪一个提交在左边,后面是一行呢?提交git show只有一个可能的祖先,并且它的单个父提交B。所以B

  1. 提取提交A的快照,然后
  2. 提取提交git show B的快照,然后
  3. 区分这两个快照。
  4. 同样,提交A只有一个直接祖先(父),而且提交B。所以M

    1. 提取L的快照,然后
    2. 提取git show M的快照,然后
    3. 区分这两个快照。
    4. 如果这是您想要的,那么有趣的问题就变成:如何在LMB,{{1}中找到每个提交的ID }和D序列?答案有点复杂,但关键命令是H,它与L基本上是相同的命令。这些命令(Mgit rev-list)执行的操作是遍历提交图。也就是说,你选择一些起点 - 在这种情况下,提交git loggit log的提示 - 并告诉Git向后走过提交,查看每个提交的父母。< / p>

      问题是,当你点击合并提交时,例如commit git rev-list,Git会回到其父级的所有。您希望限制Git在您进行合并提交时仅查找作为分支M的提示的父级。 Git有一个标志,拼写为dev。这告诉J仅遵循每个合并提交的第一个父级。

      我们还想跳过合并,因此我们可以添加dev(这不会影响回溯过程,它只会限制打印的修订ID以排除合并)。

      这会导致回答2a:--first-parent (我们将在&#34;而不是A&#34;稍后部分)。

      现在,实际上将它与git rev-list一起使用是一种痛苦,因为现在我们必须获取每个提交ID,然后在其上运行--no-merges。但是,有一种更简单的方法,因为 git rev-list --first-parent --no-merges ^A devgit rev-list本质上是相同的命令git show将每次提交显示为补丁,与git rev-list完全相同。

      这会导致回答2b:git log 。我们也不一定需要这里的git log -p;见下文。

      合并提交和组合差异

      git show做的一件特别的事情,git log -p --first-parent --no-merges ^A dev没有,是处理显示合并提交的情况,例如commit {{ 1}}。提交--no-merges两个父项,即提交git showgit diff(顺便说一句,这意味着您在提交{{1}之前提交了提交J }):-))。如果您运行J,Git将提取HK的快照并进行比较。如果您运行K,Git将提取Jgit diff H J的快照并进行比较。但是如果你运行H,Git会:

      1. 提取J的快照,然后
      2. 提取git diff K J的快照,然后
      3. 提取K(合并)的快照,最后
      4. 产生Git所谓的组合差异
      5. 步骤4中的组合差异试图以紧凑的方式显示从J git show JH的变化。在压缩更改时,Git 会抛出 K J中的版本与H中的版本匹配的任何文件。

        也就是说,假设文件KJH有一些变化。但是假设KJREADME.txt相同的。换句话说,当您执行H时,您正在从J获取更改以生成README.txt,并且K没有从另一方进行更改合并。这意味着J完全匹配一个&#34;传入的一侧&#34;,因此组合的diff 完全忽略了文件

        这意味着组合差异通常根本不显示任何内容,即使合并在新快照中拾取了一些更改。要查看这些更改,您必须制作两个差异,而不仅仅是一个。您必须从git mergeK进行一次差异,并从JREADME.txt进行另一次差异,而不是依赖于组合差异。

        使用README.txt时,您还可以通过向选项添加HJ来查看合并的组合差异。但是如果你没有要求这样做,那么Git所做的实际上是可笑的简单:它根本不用来显示差异。< / p>

        因此,这会导致回答2c:K 。我们所做的就是删除J:我们现在会看到每个合并日志消息,但没有差异。

        这是什么git log -p

        这也与你的另一个问题有关:

          顺便说一下,如果有人知道如何快速找到A而不继续向下滚动日志,我将不胜感激。

        答案是为提交-c创建符号名称。找一次其ID,然后选择一个名称,例如--ccgit log -p --first-parent ^A dev(但不要使用这些名称,因为这些名称正在使用中!)。

        所有--no-merges^A 都是:它们只是提交的符号名称,加上作为分支名称的额外属性,你可以A使用符号名称,然后结束&#34; on&#34;分支。您也可以为dev提供分支名称。你需要确保你没有master这个分支并对其进行提交,因为如果你这样做,你将成长一个新的分支,而不是让branch-name指向commit { {1}}。

        或者,您可以使标记名称指向提交dev。这与分支名称几乎完全相同。两个不同之处是:

        1. 它是一个标签名称:您无法将其作为分支进行检查,因此无法意外更改。
        2. 它是一个标记名称:如果您master,您将其作为标记向上游发送,然后其他所有人也会将其标记为。
        3. 在这种情况下,第1点对您有利,而第2点可能不是,所以由您决定优势(不能意外地改变它)是否值得冒险(可能会意外地发布它)取决于您)。

          如果您的ID为git checkout,那么您可以:

          A

          现在您拥有名称 git checkout。 (您可以稍后A删除它,但如果您不小心将其删除,您可能会继续从上游取回它。)

          回到A命令中git push --tags字符串的问题,所有A都会告诉$ git tag A <id-of-commit-A> (因此A)< em> stop 在到达提交git tag -d A时遍历提交图。提交也未显示(对于^A,未打印;对于git log,未显示在日志输出中。前缀^A符号是&#34;不是&#34;的缩写,即&#34;让我所有可以从git rev-list到达的提交,但不能从{ {1}}&#34 ;.添加git log会使Git仅遍历每个合并的第一个父级,因此我们不会进入从A合并的提交。

          git rev-list语法也可以拼写git log。请注意,这适用于^dev,但对于A来说意味着非常不同。)