我为master
分叉了一个分支。我不时将master
合并到我的分支中进行更新。
/--B--D--G--H--J--L--M--> dev (HEAD)
/ / /
-----A--C--E--F--I--K---> master
如何仅在我的分支上显示更改,不包括合并中的更改?
即仅在提交B
,D
,H
,L
,M
时显示差异。
git diff A
无效,因为它包含来自master
的合并更改。
A
而不继续向下滚动日志,我将不胜感激。
答案 0 :(得分:3)
我不清楚你正在寻找什么。但请注意:
提交商店快照。这意味着提交K
具有完整的源树,该树独立于提交A
,B
,C
等中的任何内容。同样,提交J
具有完整的快照,与A
或K
或任何其他提交中的任何内容无关。
(单词"独立"这里意味着如果你要求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
的一个差异。也就是说,您希望每次看到每个非合并提交,与其(单个)父级相比。
您可以L
和M
,依此类推。但您也可以git diff A B
和git diff B D
等等。这会将提交显示为更改,而不是快照。
如果提交存储快照而不是更改,您可能想知道这是如何实现的。 (由于大多数其他版本控制系统确实存储了更改,因此很多人都会参与其中。)这个明显矛盾的答案是git show B
查找您绘制的相同图表。
再次查看提交git show D
。在它之前发生了什么?也就是说,哪一个提交在左边,后面是一行呢?提交git show
只有一个可能的祖先,并且它的单个父提交B
。所以B
:
A
的快照,然后git show B
的快照,然后同样,提交A
只有一个直接祖先(父),而且提交B
。所以M
:
L
的快照,然后git show M
的快照,然后如果这是您想要的,那么有趣的问题就变成:如何在L
,M
,B
,{{1}中找到每个提交的ID }和D
序列?答案有点复杂,但关键命令是H
,它与L
基本上是相同的命令。这些命令(M
和git rev-list
)执行的操作是遍历提交图。也就是说,你选择一些起点 - 在这种情况下,提交git log
,git 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 dev
和git 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 show
和git diff
(顺便说一句,这意味着您在提交{{1}之前提交了提交J
}):-))。如果您运行J
,Git将提取H
和K
的快照并进行比较。如果您运行K
,Git将提取J
和git diff H J
的快照并进行比较。但是如果你运行H
,Git会:
J
的快照,然后git diff K J
的快照,然后K
(合并)的快照,最后步骤4中的组合差异试图以紧凑的方式显示从J
和 git show J
到H
的变化。在压缩更改时,Git 会抛出 K
或 J
中的版本与H
中的版本匹配的任何文件。
也就是说,假设文件K
从J
到H
有一些变化。但是假设K
和J
中README.txt
是相同的。换句话说,当您执行H
时,您正在从J
获取更改以生成README.txt
,并且K
没有从另一方进行更改合并。这意味着J
完全匹配一个&#34;传入的一侧&#34;,因此组合的diff 完全忽略了文件。
这意味着组合差异通常根本不显示任何内容,即使合并在新快照中拾取了一些更改。要查看这些更改,您必须制作两个差异,而不仅仅是一个。您必须从git merge
到K
进行一次差异,并从J
到README.txt
进行另一次差异,而不是依赖于组合差异。
使用README.txt
时,您还可以通过向选项添加H
或J
来查看合并的组合差异。但是如果你没有要求这样做,那么Git所做的实际上是可笑的简单:它根本不用来显示差异。< / p>
因此,这会导致回答2c:K
。我们所做的就是删除J
:我们现在会看到每个合并日志消息,但没有差异。
git log -p
?这也与你的另一个问题有关:
顺便说一下,如果有人知道如何快速找到A而不继续向下滚动日志,我将不胜感激。
答案是为提交-c
创建符号名称。找一次其ID,然后选择一个名称,例如--cc
或git log -p --first-parent ^A dev
(但不要使用这些名称,因为这些名称正在使用中!)。
所有--no-merges
和^A
都是:它们只是提交的符号名称,加上作为分支名称的额外属性,你可以A
使用符号名称,然后结束&#34; on&#34;分支。您也可以为dev
提供分支名称。你需要确保你没有master
这个分支并对其进行提交,因为如果你这样做,你将成长一个新的分支,而不是让branch-name指向commit { {1}}。
或者,您可以使标记名称指向提交dev
。这与分支名称几乎完全相同。两个不同之处是:
master
,您将其作为标记向上游发送,然后其他所有人也会将其标记为。在这种情况下,第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
来说意味着非常不同。)