获取合并分支分叉的提交(使用中间合并)

时间:2018-03-15 22:17:58

标签: git git-branch git-log tig

让我们使用最新的git 2.16.2和tig 2.3.3。

cd /tmp && mkdir fit && cd fit

git init
touch m1 && git add m1 && git commit -m "master 1"
touch m2 && git add m2 && git commit -m "master 2"
git checkout -b develop
touch d1 && git add d1 && git commit -m "develop 1"
git checkout master
touch m3 && git add m3 && git commit -m "master 3"
git checkout develop
git merge master --no-edit
touch d2 && git add d2 && git commit -m "develop 2"
touch d3 && git add d3 && git commit -m "develop 3"
git checkout master
git merge develop --no-edit
touch m4 && git add m4 && git commit -m "master 4"

git reflog expire --expire=now --all && git gc --prune=now --aggressive

tig enter image description here

develop分支中检索最后一次提交非常容易:

git --no-pager show -s --format=%B $(git rev-parse develop)
  

发展3

但我无法在develop分支中检索第一次提交。所以我找不到分支分支的提交。

git merge-base --fork-point develop
git rev-list develop..master
git rev-list develop master
git rev-list master develop
git rev-list ^develop master

结果没用。

我找到了问题How to get commit where merged branch forked from

的解决方案
git oldest-ancestor master develop
git oldest-ancestor develop master

结果也没用。

但是tiggit log --graph仍然可以看到develop 1develop分支的第一次提交,并且此分支是从master 2提交分叉的在master

是否可以使用当前的git控制台工具检索master 2

1 个答案:

答案 0 :(得分:2)

git --no-pager show -s --format=%B $(git rev-parse develop)

更简单:

git --no-pager show -s --format=%B develop

或:

git --no-pager log --no-walk --format=%B develop

show -slog --no-walk几乎相同;此处的关键项目是删除不必要的git rev-parse

  

但我无法在develop分支

中检索第一次提交

该分支中的第一个提交是master 1或图像中的27ee6b8(哈希ID将随提交的时间而变化)。这也是分支master中的第一个提交。

这里的问题是分支机构没有“起点”。在某种意义上,分支,即结构 - 图形片段 - 通过从结束点开始并返回到开头来到达。这意味着一些提交在许多分支上;通常, root 提交,即您在存储库中进行的第一次提交,位于每个分支上(尽管在具有多个根的存储库中,某些根可能不在某些分支上) )。

分支名称通常是一些例外 - 与该分支上的提示提交同义,这就是您不需要显式git rev-parse的原因。但是,分支名称的关键特性是它随着时间的推移移动,因此它总是命名分支的提示提交。

另见What exactly do we mean by "branch"?

如果你想标记某个特定的提交,为了以后记住它,通常的工具是Git标记。标记非常类似于分支名称,因为它标识了一个特定的提交。然而,与分支名称不同,标签永远不会移动,Git也不会自动移动它。

git reflog expire --expire=now --all

Reflogs专门用于观察参考文献的移动(随着时间的推移)。对于develop等分支名称的reflog,默认情况下保留30天或90天, 1 develop 用于标识的哈希ID。通过使它们过期,您已经删除了回溯的能力并查看develop@1develop@2等。如果您保留了它们,则可以查找存在的最早develop可能出生时,你经常会说:

05d0c47 master@{37}: clone: from ...

(表示master此时已出生。)

不幸的是,reflogs 到期,所以这不完全可靠。标签是可靠的,但可能很烦人,因为git log将使用其标签修饰提交。如果有一个过程用于查找有趣的提交,您可以使用它。在这种情况下,这样的过程:您想要合并的合并基础的提交。

要查找合并基础,找到合并本身,然后找到其父项:

m=11c63bc  # this is the merge
p1=$(git rev-parse ${m}^1)
p2=$(git rev-parse ${m}^2)

现在$p1$p2是此合并的两个父母。 (合并可以有两个以上的父项,但大多数合并只有两个。)这两个分支最后合并的共同点是两个父项的合并基础:

git merge-base --all $p1 $p2

由于只有一个合并库,因此只打印一个提交哈希。如果有几个,它会打印所有这些因为我们使用了--all。离开--all,我们会选择(显然)随机选择(实际选择的一个取决于用于查找合并基础的算法)。

和以前一样,我们不需要很多临时变量:

mbases=$(git merge-base --all ${m}^1 ${m}^2)

因为git merge-base采用与git rev-parse相同的commit-specifier语法:^1^2后缀在那里工作相同(并且在大多数Git命令中确实工作相同)。

1 到期时间是可配置的。默认情况下,30天的较短时间是针对无法从引用的当前值访问的哈希ID; 90天的默认值是针对可从参考当前值访问的哈希ID。