Re: Finding a branch point in git
- From
Felipe Contreras <felipe.contreras@gmail.com>
- Date
- May 30, 2012, 17:07 UTC
- Message-ID
- <CAMP44s0UBsVicuEcwACsm1zTT_jGau_Q20hJv4J_6uvancYJRQ@mail.gmail.com>
- In-Reply-To
- <20120528190639.GA2478@sigill.intra.peff.net>
On Mon, May 28, 2012 at 9:06 PM, Jeff King <peff@peff.net> wrote:
Show 18 quoted lines
> On Mon, May 28, 2012 at 02:36:04PM +0200, Felipe Contreras wrote: > >> > What about a history with multiple branches? >> > >> > --X--A--B--C--D----E (master) >> > \ / >> > G--H--I---J (branch X) >> > \ / >> > K--L (branch Y) >> [...] >> >> Yes, but then you would need to specify a second branch. I would avoid >> that if possible. > > I agree that is less nice. But I don't think the operation is > well-defined with a single branch. If you ask for "when did branch X > split", then in the above graph it is unclear if you meant "split from > master", or "split from Y".
If you look from the context that I explained in the first mail; it would be from *any* branch; IOW; find the first commit from branch X (G), and then find the parent. That would be the first commit where branch X started.
> Maybe you could assume "master", or assume "git symbolic-ref HEAD" as > the second branch?
No.
I think it would be easy to support this case if somehow there was a way to find all the commits that comprise a branch;
% git log branch ^<any-other-branch>
I could swear I saw such an option, but I've been looking for days and I can't find it.
IOW; all the commits were 'git branch --contains' would show 'branch' and nothing else.
Show 12 quoted lines
>> There's also another case that doesn't work: >> >> -- X -- A -- B (master) >> \ >> \ >> C (branch A) >> >> Shouldn't be hard to add checks for those cases I think. > > Actually, I think that one extends naturally. They are never merged, so > your rev-list never finds a merge commit, and you can just take the > merge base of the branch tips.
Sure, I can _just_ do that, but I need to do it :)
So, here it is... I hope people can find ways to simplify it:
find_merge ()
{
local selection extra
test "$2" && extra=" into $2"
git rev-list --min-parents=2 --grep="Merge branch '$1'$extra"
--topo-order ${3:---all} | tail -1
}branch_point ()
{
local first_merge second_merge merge
first_merge=$(find_merge $1 "" "$1 $2")
second_merge=$(find_merge $2 $1 $first_merge)
merge=${second_merge:-$first_merge}if [ "$merge" ]; then git merge-base $merge^1 $merge^2 else git merge-base $1 $2 fi }
And I've added tests: https://raw.github.com/gist/2837595/0734e7f17a4597f81c5129e3cbfee09a183e93cd/branch-point
Seems to work :)
Cheers.
-- Felipe Contreras