git cherry / git log - 由于合并而感到困惑

时间:2017-05-13 07:53:35

标签: git

我有两个分支,从一个分支到另一个分支。像这样:

> git init
Initialized empty Git repository in foo/.git/
> touch foobar; git add foobar; git commit -m "initial commit"
[master (root-commit) d109ffc] initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foobar
> git branch somebranch
> echo a >> foobar; git add foobar; git commit -m "add a"
[master 1527212] add a
 1 file changed, 1 insertion(+)
> touch anotherfile; git add anotherfile; git commit -m "add blank anotherfile"
[master 84821fc] add blank anotherfile
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 anotherfile
> git checkout somebranch; git cherry-pick -x 1527212
Switched to branch 'somebranch'
[somebranch b59ad0a] add a
 Date: Sat May 13 15:41:16 2017 +0800
 1 file changed, 1 insertion(+)
> git tree somebranch master
* b59ad0a (somebranch) add a
| * 84821fc (HEAD -> master) add blank anotherfile
| * 1527212 add a
|/
* d109ffc initial commit

在此阶段,git cherrygit log --cherry --oneline会显示我的期望:

> git cherry somebranch master
- 1527212b9047f882c7438d083505941c47ea9a5b
+ 84821fcb3d33d41b64dddcc56728dd3e22466e4a
> git log --cherry --oneline somebranch...master
+ 84821fc (HEAD -> master) add blank anotherfile
= 1527212 add a

但是,如果我将两个分支合并在一起,则会丢失此输出 - git cherrygit log --cherry都无法将樱桃选择的提交识别为相同:

> git checkout master
Already on 'master'
> git merge somebranch
Merge made by the 'recursive' strategy.
> git tree
*   90810f6 (HEAD -> master) Merge branch 'somebranch'
|\
| * b59ad0a (somebranch) add a
* | 84821fc add blank anotherfile
* | 1527212 add a
|/
* d109ffc initial commit
> git cherry somebranch master
+ 1527212b9047f882c7438d083505941c47ea9a5b
+ 84821fcb3d33d41b64dddcc56728dd3e22466e4a
> git log --cherry --oneline somebranch...master
+ 84821fc add blank anotherfile
+ 1527212 add a

有没有办法让git表明这些提交是相同的,即使它们已经合并在一起了?

1 个答案:

答案 0 :(得分:1)

问题出现了,因为Git不再查看其中一个提交。

请记住,三点语法(在git cherry A B的情况下隐含,在git log --cherry A...B的情况下是明确的)意味着采用对称差异:提交可从 A B ,但两者都不是。

(我认为此处git treegit log --all --decorate --oneline --graph的别名:)

> git tree
*   90810f6 (HEAD -> master) Merge branch 'somebranch'
|\
| * b59ad0a (somebranch) add a
* | 84821fc add blank anotherfile
* | 1527212 add a
|/
* d109ffc initial commit

名称master表示90810f6,名称somebranch表示b59ad0a。我们要做的第一件事是找到可以从这两个提交中获得的提交,记住我们如何达到它们:

  • 90810f6:从90810f6 1
  • 到达
  • b59ad0a:来自b59ad0a 90810f6:discard
  • 84821fc:从90810f6
  • 到达
  • 1527212:从84821fc
  • 到达
  • d109ffc:双方也达成了协议:discard

我们已经抛出了一个有趣的(樱桃等效的)b59ad0a提交,所以我们永远不会看到它。

正如the documentation告诉我们的那样,--cherry是:

  

--right-only --cherry-mark --no-merges的同义词......

所以从我们的三个尚未丢弃的提交列表中,我们也抛出了90810f6,因为它是一个合并。这留下了我们的两个提交。

  

我有没有办法让git表明这些提交是一样的,即使它们已经合并在一起了?

您必须从合并下方开始检查。使用任何方法(请参阅the gitrevisions documentation了解拼写的许多方法)从master标识的合并提交的第一个父级开始列表,例如:

git log --cherry --oneline somebranch...master~1

(我们知道这只是因为我们查看了图表并看到master是合并)。请注意,我们可以使用^1^2后缀指定提供给合并的两个提交:

git log --cherry --oneline master^2...master^1

符号master^1master~1的含义完全相同,因为每个符号都表示向后移动一步到第一个父级。 master^2 vs master~2不是这种情况:前者意味着"第二父母"而后者意味着"第一父母的第一父母"。

1 提交总是达到自己,即使这听起来含糊不清。 : - )