tags:

views:

867

answers:

5

I have a repository with branches master and A and lots of merge activity between the two. How can I find the commit in my repository when branch A was created based on master?

My repository basically looks like this:

-- X -- A -- B -- C -- D -- F  (master) 
          \     /   \     /
           \   /     \   /
             G -- H -- I -- J  (branch A)

I'm looking for revision A, which is not what "git merge-base (--all)" finds.

Regards,

Jochen

+9  A: 

You may be looking for git merge-base:

git merge-base finds best common ancestor(s) between two commits to use in a three-way merge. One common ancestor is better than another common ancestor if the latter is an ancestor of the former. A common ancestor that does not have any better common ancestor is a best common ancestor, i.e. a merge base. Note that there can be more than one merge base for a pair of commits.

Greg Hewgill
Note also the `--all` option to "`git merge-base`"
Jakub Narębski
+5  A: 

In general, this is not possible. In a branch history a branch-and-merge before a named branch was branched off and an intermediate branch of two named branches look the same.

In git, branches are just the current names of the tips of sections of history. They don't really have a strong identity.

This isn't usually a big issue as the merge-base (see Greg Hewgill's answer) of two commits is usually much more useful, giving the most recent commit which the two branches shared.

Charles Bailey
A: 

You can examine the reflog of branch A to find from which commit it was created, as well as the full history of which commits that branch pointed to. Reflogs are in .git/logs.

Paggas
I don't think this works in general because the reflog can be pruned. And I don't think (?) reflogs get pushed either, so this would only work in a single-repo situation.
garyo
+2  A: 

How about something like

git log --pretty=oneline master > 1
git log --pretty=oneline branch_A > 2

git rev-parse `diff 1 2 | tail -1 | cut -c 3-42`^
Karl
This works. It's really cumbersome but it's the only thing I've found that actually seems to do the job.
garyo
Git alias equivalent: `diverges = !bash -c 'git rev-parse $(diff <(git log --pretty=oneline ${1}) <(git log --pretty=oneline ${2}) | tail -1 | cut -c 3-42)^'` (with no temporary files)
conny
+5  A: 

I've used git rev-list for this sort of thing. For example,

$ git rev-list --boundary branch-a...master | grep ^- | cut -c2-

will spit out the branch point. Now, it's not perfect; since you've merged master into branch A a couple of times, that'll split out a couple possible branch points (basically, the original branch point and then each point at which you merged master into branch A). However, it should at least narrow down the possibilities.

I've added that command to my aliases in ~/.gitconfig as:

[alias]
    diverges = !sh -c 'git rev-list --boundary $1...$2 | grep ^- | cut -c2-'

so I can call it as:

$ git diverges branch-a master
mipadi