我怎样才能看到另一个分支从哪个分支分叉?

Fre*_*abe 27 git branch

我的git存储库有三个分支devel,stablecustomers/acme_patches.很久以前,它stable是分叉的devel,并且所有的错误修正都发生在stable.时不时地stable被合并回来devel.customers/acme_patches是一个具有一些客户特定补丁的分支.该分支未合并为develstable.

一些ASCII艺术来说明场景:

            o---o---o          customers/acme_patches?
           /
  o---o---1---o---o---o        stable
 /     \           \
o---o---o---2---o---o---o---o  devel
             \
              o---o---o        customers/acme_patches?

现在我想知道:

customers/acme_patches分叉的是什么分支- devel或者stable?我只是知道它过去曾分离过其中一个,但我不知道哪个.例如它可能已经提交12在上图中.

我一直在玩git log --oneline --graph,gitk但自从customers/acme_patches分开了几百次提交之后,很难按照画出的线条.

是否有一个快速命令(一个小脚本也可以),它可以以某种方式跟随提交customers/acme_patches向后找到第一个提交有两个孩子(叉点),然后确定是否在stable或在中提交devel

在最好的情况下,我可以执行类似的操作(请原谅,我在Windows上):

C:\src> git fork-origin customers/acme_patches
stable
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 24

使用git 1.9/2.0(2014年第1季度),您可以git merge-base --fork-point根据Git请求最佳共同祖先.

你可以看到这个新选项:


而且,由于提交ad8261d约翰饲养(johnkeeping),git rebase可以使用相同的新--fork-point选项,它可以派上用场,如果您需要衍合分支像customers/acme_patchesdevel.
(我不是说这在你的具体情况下会有意义)


注意:Git 2.16(2018年第一季度)确实澄清并增强了" merge-base --fork-point"的文档,因为很清楚它的计算方法,但不是为什么/为什么.

Junio C Hamano()提交6d1700b(2017年11月9日).(由Junio C Hamano合并- -提交022dd4a,2017年11月27日)gitster
gitster

merge-base --fork-point doc:澄清示例和失败模式

图示的历史用于解释--fork-point名为三个关键点的模式提交从最旧到最新的B3,B2和B1,这很难阅读.
将它们重新标记为B0,B1,B2.
还说明了使用该--fork-point设施的rebase之后的历史.

该文本已经提到使用reflog,但描述并不清楚我们通过使用reflog获得了什么好处.
澄清它是要找到已知位于远程跟踪分支顶端的提交.
这反过来又需要用户知道基本假设的后果,即,reflog条目的到期将使得无法确定哪些提交位于远程跟踪分支的尖端,并且我们在有疑问时失败(而不是随机给出)甚至没有警告的错误结果).
另一个限制是,如果你没有从远程跟踪分支的尖端而是从中间分叉,它将没有用处.
描述他们.

所以文档现在写道:

在使用topic创建的分支上工作后git checkout -b topic origin/master,远程跟踪分支的历史 origin/master可能已经被重绕并重建,从而导致了这种形状的历史:

                 o---B2
                /
---o---o---B1--o---o---o---B (origin/master)
        \
         B0
          \
           D0---D1---D (topic)
Run Code Online (Sandbox Code Playgroud)

其中,origin/master用于指向在提交B0,B1,B2,现在它在B处点,你topic当分支开始在它的背面顶部origin/master是在B0,和你建立三个提交,D0,D1和d,在它的上面.
想象一下,您现在想要topic在更新的基础上重新设计您所做的工作origin/master.

在这种情况下,git merge-base origin/master topic将返回B0的家长在上面的图片,但是B0^..D不是你想重播对B的顶部提交的范围(它包括B0,这是不是你写的东西,它是一个提交其他当它的尖端从B0移动到B1时丢弃.

git merge-base --fork-point origin/master topic旨在帮助这种情况.
它不仅需要B,还需要B0,B1和B2(即存储库的reflog知道的远程跟踪分支的旧技巧),以查看构建主题分支的提交并找到B0,允许您仅重放对你主题的提交,不包括后来丢弃的提交.

于是

$ fork_point=$(git merge-base --fork-point origin/master topic)
Run Code Online (Sandbox Code Playgroud)

会找到B0,和

$ git rebase --onto origin/master $fork_point topic
Run Code Online (Sandbox Code Playgroud)

将重放B顶部的D0,D1和D以创建此形状的新历史记录:

         o---B2
        /
---o---o---B1--o---o---o---B (origin/master)
    \                   \
     B0                  D0'--D1'--D' (topic - updated)
      \
       D0---D1---D (topic - old)
Run Code Online (Sandbox Code Playgroud)

需要注意的是,您的存储库中较旧的reflog条目可能会过期git gc.
如果远程跟踪分支的reflog中不再出现B0 origin/master,则该--fork-point模式显然无法找到并失败,从而避免给出随机且无用的结果(例如B0的父级,就像没有--fork-point选项的同一命令一样).

此外,您使用--fork-point模式的远程跟踪分支必须是您的主题从其提示分叉的主题.
如果你从旧犯比前端分叉,这种模式不会找到叉点(想象一下在上面的示例历史B0不存在, origin/master开始在B1,转移到B2,然后B,你叉你在话题origin/master^的时候origin/master了B1;历史的形状与上面相同,没有B0,B1的父级是git merge-base origin/master topic正确找到的,但--fork-point模式不会,因为它不是以前提交的提交之一origin/master) .


Ant*_*sse 7

嗯,这个答案可能没有完美的解决方案.我的意思是fork-origingit中没有等价物(据我所知).由于stable分支合并到devel,你acme_patches(1)是两个develstable分支.

你可能做的是:

git branch --contains $(git merge-base customers/acme_patches devel stable)
Run Code Online (Sandbox Code Playgroud)

如果你有稳定而不开发,或开发并且不稳定,那么你就知道它来自哪里.

例如,在案例2中,您将拥有

$ git branch --contains $(git merge-base customers/acme_patches devel stable)
customers/acme_patches
devel
Run Code Online (Sandbox Code Playgroud)

而在案例1中你会有

$ git branch --contains $(git merge-base customers/acme_patches devel stable)
customers/acme_patches
devel
stable
Run Code Online (Sandbox Code Playgroud)

因为它现在在两个分支上(因为从稳定到开发的合并)