All of lore.kernel.org
 help / color / mirror / Atom feed
* Find out on which branch a commit was originally made
@ 2010-09-18  9:19 Stefan Haller
  2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
  2010-09-24 18:26 ` Bryan Drewery
  0 siblings, 2 replies; 33+ messages in thread
From: Stefan Haller @ 2010-09-18  9:19 UTC (permalink / raw)
  To: git

I'm trying to pursuade my co-workers to switch from Subversion to Git;
some of them prefer Mercurial.

One concern that they are raising is that in Git there doesn't seem to
be an easy way to find out on which branch a given commit was originally
made, after the branch is merged back and deleted. They consider this a
show-stopper.  In Mercurial, branch information is meta data attached to
each commit, so you can easily get this information even after a branch
is closed.

Three questions:

1) Is this not something that Git users miss sometimes?  Why not?

2) Is there an easy way to get this information that I might have
missed?  (Typical use-case: you blame a line of code with git gui blame,
choose "Show history context" to show the changeset in gitk, and from
there you want to go up to the next merge commit to see if the merge
commit message mentions the name of the branch. I can't seem to figure
out how to find this merge commit in gitk, and besides, "Show history
context" shows me only 7 days of context by default, so the merge commit
is likely not to be in my current list anyway.)

3) As a possible work-around, they suggest to require encoding the
branch information in some format in the commit messages, maybe
automatically with a commit-msg hook.  Does this sound like a feasible
idea?  One drawback would be that it becomes awkward when you
accidentally make a commit on the wrong branch, and want to rebase it
onto the correct one.

Any insights and thoughts about this are much appreciated.

Thanks,
   Stefan


-- 
Stefan Haller
Berlin, Germany
http://www.haller-berlin.de/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18  9:19 Find out on which branch a commit was originally made Stefan Haller
@ 2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
  2010-09-18 10:02   ` Ævar Arnfjörð Bjarmason
                     ` (2 more replies)
  2010-09-24 18:26 ` Bryan Drewery
  1 sibling, 3 replies; 33+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-09-18  9:58 UTC (permalink / raw)
  To: Stefan Haller; +Cc: git

On Sat, Sep 18, 2010 at 09:19, Stefan Haller <lists@haller-berlin.de> wrote:
> I'm trying to pursuade my co-workers to switch from Subversion to Git;
> some of them prefer Mercurial.
>
> One concern that they are raising is that in Git there doesn't seem to
> be an easy way to find out on which branch a given commit was originally
> made, after the branch is merged back and deleted. They consider this a
> show-stopper.  In Mercurial, branch information is meta data attached to
> each commit, so you can easily get this information even after a branch
> is closed.
>
> Three questions:
>
> 1) Is this not something that Git users miss sometimes?  Why not?
>
> 2) Is there an easy way to get this information that I might have
> missed?  (Typical use-case: you blame a line of code with git gui blame,
> choose "Show history context" to show the changeset in gitk, and from
> there you want to go up to the next merge commit to see if the merge
> commit message mentions the name of the branch. I can't seem to figure
> out how to find this merge commit in gitk, and besides, "Show history
> context" shows me only 7 days of context by default, so the merge commit
> is likely not to be in my current list anyway.)
>
> 3) As a possible work-around, they suggest to require encoding the
> branch information in some format in the commit messages, maybe
> automatically with a commit-msg hook.  Does this sound like a feasible
> idea?  One drawback would be that it becomes awkward when you
> accidentally make a commit on the wrong branch, and want to rebase it
> onto the correct one.

    You want to do X, and you think Y is the best way of doing so.
Instead of asking about X, you ask about Y.
    — from Re: sequencial file naming by Abigail

Your Y is encoding the name of the current branch at commit-time, the
you haven't told us. Why do your co-workers think this is essential to
the point that they can't get by without it? What problem are they
trying to solve?

But to answer your question then no, Git doesn't track this
information. Because we think it's irrelevant.

As an example of how irrelevant it is consider my huge ab/i18n series
(you may have spotted it on the list). It's currently composed of 140
patches.

If Git tracked the branch at commit time that series would contain a
bunch of useless metadata. The series is currently composed of commits
which were originally created on at least some of these branches:

    $ git branch -l |grep -e gettext -e i18n
    * ab/i18n
      ab/i18n-add-translations
      ab/i18n-all
      ab/i18n-all-continue
      ab/i18n-continue
      ab/i18n-continue-hi.po
      ab/i18n-continue-more
      ab/i18n-continue-with-hindi
      ab/i18n-for-junio
      ab/i18n-for-junio-with-docs
      ab/i18n-gettextize
      ab/i18n-v2
      debug-gettext-poison
      disable-gettext-by-default-in-releases
      gettext-remove-old-sanity-test
      gettextize-git-in-german
      gettextize-git-mainporcelain
      gettextize-git-mainporcelain-even-more
      gettextize-git-mainporcelain-more
      gettextize-git-mainporcelain-v2
      gettextize-git-mainporcelain-v3
      gettextize-git-mainporcelain-with-perl
      minor-gettext-infrastructure-fixes

But nobody will ever care what branch name I just happened to pick
while I was hacking some patch, why should they? Why does it matter
than I commited some commit on a Solaris box on a branch called
`ab/i18n-oh-man-i-hate-solaris-will-this-just-bloddy-work-already' ?

What Git *does* track however when you do `git merge topic` is the
name of the `topic` branch you're merging into some other branch,
e.g. here (from git-merge(1)):

                     A---B---C topic
                    /         \
               D---E---F---G---H master

Even though A B and C might have been commited on branches called
`blah`, `bluh` and `blarghl` you'll never know. You'll just know that
someone put them all together on a branch called `topic` and that
someone later merged that into master in the main repository. E.g.:

    Merge: A G
    Author: Some Guy <some-guy@example.com>
    Date:   <....>

        Merge branch 'topic'

From there you can *infer* that A-B-C came from the topic branch,
because of that merge commit and that the DAG doesn't meet master
until commit E.

But you can't ever get info about `blah`, `bluh` and `blarghl` back
out of A-B and C again unless you track those branches down in
someone's development repository.

Why? Because who cares about `blah`, `bluh` and `blarghl`, really?

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
@ 2010-09-18 10:02   ` Ævar Arnfjörð Bjarmason
  2010-09-18 11:28   ` Tor Arntsen
  2010-09-18 15:26   ` Stefan Haller
  2 siblings, 0 replies; 33+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-09-18 10:02 UTC (permalink / raw)
  To: Stefan Haller; +Cc: git

On Sat, Sep 18, 2010 at 09:58, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
>    You want to do X, and you think Y is the best way of doing so.
> Instead of asking about X, you ask about Y.
>    — from Re: sequencial file naming by Abigail
>
> Your Y is encoding the name of the current branch at commit-time, the
> you haven't told us.

"the X you haven't told us", damn PEBKAC problems.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
  2010-09-18 10:02   ` Ævar Arnfjörð Bjarmason
@ 2010-09-18 11:28   ` Tor Arntsen
  2010-09-18 15:26   ` Stefan Haller
  2 siblings, 0 replies; 33+ messages in thread
From: Tor Arntsen @ 2010-09-18 11:28 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Ævar Arnfjörð Bjarmason, git

On Sat, Sep 18, 2010 at 11:58, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
[..]
> What Git *does* track however when you do `git merge topic` is the
> name of the `topic` branch you're merging into some other branch,
> e.g. here (from git-merge(1)):
>
>                     A---B---C topic
>                    /         \
>               D---E---F---G---H master
>
> Even though A B and C might have been commited on branches called
> `blah`, `bluh` and `blarghl` you'll never know. You'll just know that
> someone put them all together on a branch called `topic` and that
> someone later merged that into master in the main repository. E.g.:
>
>    Merge: A G
>    Author: Some Guy <some-guy@example.com>
>    Date:   <....>
>
>        Merge branch 'topic'
>
> >From there you can *infer* that A-B-C came from the topic branch,
> because of that merge commit and that the DAG doesn't meet master
> until commit E.
[..]

However, you can see it explictly if you add --log when merging, i.e.
git merge --no-ff --log topic
(you'll get a list of one-line commit messages from those commits
merged into master from topic).
It doesn't identify the commits, only the commit messages. Therefore I
add problem report IDs into my oneline-messages, and I get a shortlist
of exactly what was fixed by a given merge. This is sufficient support
for me, I too don't care where a commit _originally_ came from, before
it arrived into the branch that I at some point merge to the delivery
branch.

-Tor

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
  2010-09-18 10:02   ` Ævar Arnfjörð Bjarmason
  2010-09-18 11:28   ` Tor Arntsen
@ 2010-09-18 15:26   ` Stefan Haller
  2010-09-18 16:41     ` Artur Skawina
  2010-09-19 18:30     ` Robin Rosenberg
  2 siblings, 2 replies; 33+ messages in thread
From: Stefan Haller @ 2010-09-18 15:26 UTC (permalink / raw)
  To: Ævar Arnfjör? Bjarmason; +Cc: git

Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:

>     You want to do X, and you think Y is the best way of doing so.
> Instead of asking about X, you ask about Y.

Erm, not really; I explicitly mentioned Y as "a possible workaround"
only.  Anyway...

> Why do your co-workers think this is essential to the point that they
> can't get by without it? What problem are they trying to solve?

It's a common situation that you want to know why a certain piece of
code is written the way it is.  So you blame it, you eventually end up
at a certain interesting changeset, and hopefully the commit message
tells you enough about why the change was made.  If it doesn't, then it
can help a lot to know a bit more about the context of the change, i.e.
what topic it was part of.

> What Git *does* track however when you do `git merge topic` is the
> name of the `topic` branch you're merging into some other branch,
> e.g. here (from git-merge(1)):
> 
>                      A---B---C topic
>                     /         \
>                D---E---F---G---H master
> 
> Even though A B and C might have been commited on branches called
> `blah`, `bluh` and `blarghl` you'll never know. You'll just know that
> someone put them all together on a branch called `topic` and that
> someone later merged that into master in the main repository. E.g.:
> 
>     Merge: A G
>     Author: Some Guy <some-guy@example.com>
>     Date:   <....>
> 
>         Merge branch 'topic'
> 
> From there you can *infer* that A-B-C came from the topic branch,

OK, that's pretty much the same as what I had in mind.  (We're
simple-minded, so for us "original branch" and topic branch is the same
most of the time.)

The question is the same though: if I hit commit B while blaming, how do
I know what topic it was a part of?  For that, I need to find commit H
which will tell me, right?  How do I do that?

-Stefan


-- 
Stefan Haller
Berlin, Germany
http://www.haller-berlin.de/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18 15:26   ` Stefan Haller
@ 2010-09-18 16:41     ` Artur Skawina
  2010-09-19  9:45       ` Stefan Haller
  2010-09-19 18:30     ` Robin Rosenberg
  1 sibling, 1 reply; 33+ messages in thread
From: Artur Skawina @ 2010-09-18 16:41 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Ævar Arnfjör? Bjarmason, git

On 09/18/10 17:26, Stefan Haller wrote:
> Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:
>>                      A---B---C topic
>>                     /         \
>>                D---E---F---G---H master

 The question is the same though: if I hit commit B while blaming, how do
> I know what topic it was a part of?  For that, I need to find commit H
> which will tell me, right?  How do I do that?

git rev-list --ancestry-path --merges --reverse B..master --format=oneline

> One concern that they are raising is that in Git there doesn't seem to
> be an easy way to find out on which branch a given commit was originally
> made, after the branch is merged back and deleted. They consider this a
> show-stopper.  In Mercurial, branch information is meta data attached to
> each commit, so you can easily get this information even after a branch
> is closed.

Don't do that, then. 
IOW if you know you could still need the old branch info, make an alias
that doesn't actually delete the branch after merging, but moves the ref
away, eg 'topic-name' -> "merged/topic-name" or just adds a
"merged/topic-name" tag. Then simply checking from which "merged/*"
branch/tag the offending commit is reachable would be enough.
Deleting a merged branch does not do anything more than removing the
reference (to 'C' in the above example), all the history stays around
forever anyway...

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18 16:41     ` Artur Skawina
@ 2010-09-19  9:45       ` Stefan Haller
  2010-09-19 12:54         ` Clemens Buchacher
                           ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Stefan Haller @ 2010-09-19  9:45 UTC (permalink / raw)
  To: Artur Skawina; +Cc: Ævar Arnfjör? Bjarmason, git

Artur Skawina <art.08.09@gmail.com> wrote:

> On 09/18/10 17:26, Stefan Haller wrote:
> > Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:
> >>                      A---B---C topic
> >>                     /         \
> >>                D---E---F---G---H master
> 
> > The question is the same though: if I hit commit B while blaming, how do
> > I know what topic it was a part of?  For that, I need to find commit H
> > which will tell me, right?  How do I do that?
> 
> git rev-list --ancestry-path --merges --reverse B..master --format=oneline

Thanks, this is helpful.  (However, my co-workers will probably laugh at
me if I suggest they remember a command such as this for what they think
should be a very simple operation.)

There's a problem though for commits that are far back in history:

               A---B---C topic
              /         \
         D---E---F---G---H---I---J---K---L---M---N master
                                  \         /
                                   O---P---Q another-topic

Your command also shows M, which is not interesting at all in this
context.  Ideally it should stop at the first command that's common to
topic and master.  Is there an easy way to achieve that?

> IOW if you know you could still need the old branch info, make an alias
> that doesn't actually delete the branch after merging, but moves the ref
> away, eg 'topic-name' -> "merged/topic-name" or just adds a
> "merged/topic-name" tag. Then simply checking from which "merged/*"
> branch/tag the offending commit is reachable would be enough.

Same problem here: this also shows all branches that were created and
merged after the original topic was merged.  (In the example above, it
will also list another-topic.)  This makes it pretty much impossible to
find the one I'm interested in.


-- 
Stefan Haller
Berlin, Germany
http://www.haller-berlin.de/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19  9:45       ` Stefan Haller
@ 2010-09-19 12:54         ` Clemens Buchacher
  2010-09-19 14:03         ` Artur Skawina
  2010-09-19 14:08         ` Stefan Haller
  2 siblings, 0 replies; 33+ messages in thread
From: Clemens Buchacher @ 2010-09-19 12:54 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Artur Skawina, Ævar Arnfjör? Bjarmason, git

[-- Attachment #1: Type: text/plain, Size: 284 bytes --]

On Sun, Sep 19, 2010 at 11:45:25AM +0200, Stefan Haller wrote:
> 
> Your command also shows M, which is not interesting at all in this
> context.  Ideally it should stop at the first command that's common to
> topic and master.  Is there an easy way to achieve that?

head -1?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19  9:45       ` Stefan Haller
  2010-09-19 12:54         ` Clemens Buchacher
@ 2010-09-19 14:03         ` Artur Skawina
  2010-09-19 14:08         ` Stefan Haller
  2 siblings, 0 replies; 33+ messages in thread
From: Artur Skawina @ 2010-09-19 14:03 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Ævar Arnfjör? Bjarmason, git

On 09/19/10 11:45, Stefan Haller wrote:
> Artur Skawina <art.08.09@gmail.com> wrote:
> 
>> On 09/18/10 17:26, Stefan Haller wrote:
>>> Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:
>>>>                      A---B---C topic
>>>>                     /         \
>>>>                D---E---F---G---H master
>>
>>> The question is the same though: if I hit commit B while blaming, how do
>>> I know what topic it was a part of?  For that, I need to find commit H
>>> which will tell me, right?  How do I do that?
>>
>> git rev-list --ancestry-path --merges --reverse B..master --format=oneline
> 
> Thanks, this is helpful.  (However, my co-workers will probably laugh at
> me if I suggest they remember a command such as this for what they think
> should be a very simple operation.)

An alias such as "git show-merges-since B" might help.

> There's a problem though for commits that are far back in history:
> 
>                A---B---C topic
>               /         \
>          D---E---F---G---H---I---J---K---L---M---N master
>                                   \         /
>                                    O---P---Q another-topic
> 
> Your command also shows M, which is not interesting at all in this

But you're only interested in the name of the original topic branch,
right? Then the first merge will tell you that; I omitted "| head -1"
from the cmdline above, just in case the history isn't as simple as
in this graph.

> context.  Ideally it should stop at the first command that's common to
> topic and master.  Is there an easy way to achieve that?

Well, as you've explicitly deleted the 'topic' ref, how is git supposed
to find it?

The above "git rev-list" will give you either the merge w/ the info you
are looking for, or a list of merge commits that you'll have to filter
(grep etc) to find the first one containing the answer.

>> IOW if you know you could still need the old branch info, make an alias
>> that doesn't actually delete the branch after merging, but moves the ref
>> away, eg 'topic-name' -> "merged/topic-name" or just adds a
>> "merged/topic-name" tag. Then simply checking from which "merged/*"
>> branch/tag the offending commit is reachable would be enough.
> 
> Same problem here: this also shows all branches that were created and
> merged after the original topic was merged.  (In the example above, it
> will also list another-topic.)  This makes it pretty much impossible to

Yes. "git merge-base master another-topic" would return 'J' and if 'B'
is still reachable from 'J' then 'another-topic' isn't the answer and
you have to keep looking. So it's a bit more complicated.

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19  9:45       ` Stefan Haller
  2010-09-19 12:54         ` Clemens Buchacher
  2010-09-19 14:03         ` Artur Skawina
@ 2010-09-19 14:08         ` Stefan Haller
  2010-09-19 16:38           ` Artur Skawina
  2 siblings, 1 reply; 33+ messages in thread
From: Stefan Haller @ 2010-09-19 14:08 UTC (permalink / raw)
  To: Artur Skawina; +Cc: Ævar Arnfjör? Bjarmason, git

Stefan Haller <lists@haller-berlin.de> wrote:

> Artur Skawina <art.08.09@gmail.com> wrote:
> 
> > On 09/18/10 17:26, Stefan Haller wrote:
> > > Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:
> > >>                      A---B---C topic
> > >>                     /         \
> > >>                D---E---F---G---H master
> > 
> > > The question is the same though: if I hit commit B while blaming, how do
> > > I know what topic it was a part of?  For that, I need to find commit H
> > > which will tell me, right?  How do I do that?
> > 
> > git rev-list --ancestry-path --merges --reverse B..master --format=oneline
> 
> Thanks, this is helpful.  (However, my co-workers will probably laugh at
> me if I suggest they remember a command such as this for what they think
> should be a very simple operation.)
> 
> There's a problem though for commits that are far back in history:
> 
>                A---B---C topic
>               /         \
>          D---E---F---G---H---I---J---K---L---M---N master
>                                   \         /
>                                    O---P---Q another-topic
> 
> Your command also shows M, which is not interesting at all in this
> context.  Ideally it should stop at the first command that's common to
> topic and master.

No, that's not what I need either.  After thinking about it more, I
think what I want is "of all merges in the ancestry path from B to
master, show only those whose first parent can't reach B."  The result
is the list of all merges that were involved in bringing B to master.

Here's what I came up with:

#!/bin/sh

git rev-list --ancestry-path --merges --reverse "$1".."${2-master}" \
  | while read ref
do
  if [ -z "$(git rev-list --ancestry-path "$1".."$ref"^)" ]
  then
    git --no-pager log -1 --pretty=oneline "$ref"
  fi
done

It's pretty inefficient, but seems to get the job done. Is there a
smarter way to achieve the same?

-Stefan


-- 
Stefan Haller
Berlin, Germany
http://www.haller-berlin.de/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19 14:08         ` Stefan Haller
@ 2010-09-19 16:38           ` Artur Skawina
  0 siblings, 0 replies; 33+ messages in thread
From: Artur Skawina @ 2010-09-19 16:38 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Ævar Arnfjör? Bjarmason, git

On 09/19/10 16:08, Stefan Haller wrote:
> Stefan Haller <lists@haller-berlin.de> wrote:
> 
>> Artur Skawina <art.08.09@gmail.com> wrote:
>>
>>> On 09/18/10 17:26, Stefan Haller wrote:
>>>> Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:
>>>>>                      A---B---C topic
>>>>>                     /         \
>>>>>                D---E---F---G---H master
>>>
>>>> The question is the same though: if I hit commit B while blaming, how do
>>>> I know what topic it was a part of?  For that, I need to find commit H
>>>> which will tell me, right?  How do I do that?
>>>
>>> git rev-list --ancestry-path --merges --reverse B..master --format=oneline
>>
>> Thanks, this is helpful.  (However, my co-workers will probably laugh at
>> me if I suggest they remember a command such as this for what they think
>> should be a very simple operation.)
>>
>> There's a problem though for commits that are far back in history:
>>
>>                A---B---C topic
>>               /         \
>>          D---E---F---G---H---I---J---K---L---M---N master
>>                                   \         /
>>                                    O---P---Q another-topic
>>
>> Your command also shows M, which is not interesting at all in this
>> context.  Ideally it should stop at the first command that's common to
>> topic and master.
> 
> No, that's not what I need either.  After thinking about it more, I
> think what I want is "of all merges in the ancestry path from B to
> master, show only those whose first parent can't reach B."  The result
> is the list of all merges that were involved in bringing B to master.
> 
> Here's what I came up with:
> 
> #!/bin/sh
> 
> git rev-list --ancestry-path --merges --reverse "$1".."${2-master}" \
>   | while read ref
> do
>   if [ -z "$(git rev-list --ancestry-path "$1".."$ref"^)" ]
>   then
>     git --no-pager log -1 --pretty=oneline "$ref"
>   fi
> done
> 
> It's pretty inefficient, but seems to get the job done. Is there a
> smarter way to achieve the same?

This would work, and i don't see a way to optimize it in git-speak,
given that you don't want to see any extra trailing merges. At least,
not if it's supposed to be generic; consider a case where the 'topic'
merges another 'subtopic' and is then merged into a 'supertopic', which
is then merged to 'master'. Maybe somebody else has an idea?

For me, this seems like overkill, the merge list given by "git rev-list"
should be more than enough to figure out which branch the commit came
from. And if not - either your shell script or walking the history
("--parents" option) w/ a script would do. But i can't even imagine how
such a history would have to look like... 

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18 15:26   ` Stefan Haller
  2010-09-18 16:41     ` Artur Skawina
@ 2010-09-19 18:30     ` Robin Rosenberg
  2010-09-19 22:03       ` Seth Robertson
  1 sibling, 1 reply; 33+ messages in thread
From: Robin Rosenberg @ 2010-09-19 18:30 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Ævar Arnfjör? Bjarmason, git

lördagen den 18 september 2010 17.26.08 skrev  Stefan Haller:
> Ævar Arnfjör? Bjarmason <avarab@gmail.com> wrote:
> >     You want to do X, and you think Y is the best way of doing so.
> > 
> > Instead of asking about X, you ask about Y.
> 
> Erm, not really; I explicitly mentioned Y as "a possible workaround"
> only.  Anyway...
> 
> > Why do your co-workers think this is essential to the point that they
> > can't get by without it? What problem are they trying to solve?
> 
> It's a common situation that you want to know why a certain piece of
> code is written the way it is.  So you blame it, you eventually end up
> at a certain interesting changeset, and hopefully the commit message
> tells you enough about why the change was made.  If it doesn't, then it
> can help a lot to know a bit more about the context of the change, i.e.
> what topic it was part of.

What most people do (I think) is to include a reference to a ticket in a issue 
tracker. JGit/EGit adds Bug:-line in the footer. Others add the ticket number 
in the Subject. This much informative than a branch name.  It also allows
you to fix unrelated bugs on your branch. 

-- robin

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19 18:30     ` Robin Rosenberg
@ 2010-09-19 22:03       ` Seth Robertson
  2010-09-19 23:12         ` Artur Skawina
  0 siblings, 1 reply; 33+ messages in thread
From: Seth Robertson @ 2010-09-19 22:03 UTC (permalink / raw)
  To: git


>>>                A---B---C topic
>>>               /         \
>>>          D---E---F---G---H---I---J---K---L---M---N master
>>>                                   \         /
>>>                                    O---P---Q another-topic

>> No, that's not what I need either.  After thinking about it more, I
>> think what I want is "of all merges in the ancestry path from B to
>> master, show only those whose first parent can't reach B."  The result
>> is the list of all merges that were involved in bringing B to master.


> This would work, and i don't see a way to optimize it in git-speak,
> given that you don't want to see any extra trailing merges. [...]

The provided command actually doesn't work for me for all cases.  It
works for the simple case of "B", but does not work for "F", because F
saw merge H & M.  I think we need --not --first-parent, except that
doesn't actually work in this case either.  However, if we get the
full --first-parent rev-list and look for our commit, that works.
This is incredibly painful, though.

----------------------------------------------------------------------
#!/bin/sh
TARGET=`git rev-list -n 1 $1`
git branch -a --contains $1 | sed 's/^\** *//' | grep -v ' -> ' |
while read br; do
 if git rev-list --first-parent $br | grep -q "$TARGET"; then
  echo $br
 fi
done
----------------------------------------------------------------------

					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19 22:03       ` Seth Robertson
@ 2010-09-19 23:12         ` Artur Skawina
  2010-09-19 23:54           ` Seth Robertson
  0 siblings, 1 reply; 33+ messages in thread
From: Artur Skawina @ 2010-09-19 23:12 UTC (permalink / raw)
  To: Seth Robertson; +Cc: git

On 09/20/10 00:03, Seth Robertson wrote:
>>>>                A---B---C topic
>>>>               /         \
>>>>          D---E---F---G---H---I---J---K---L---M---N master
>>>>                                   \         /
>>>>                                    O---P---Q another-topic
> 
>>> No, that's not what I need either.  After thinking about it more, I
>>> think what I want is "of all merges in the ancestry path from B to
>>> master, show only those whose first parent can't reach B."  The result
>>> is the list of all merges that were involved in bringing B to master.
> 
> 
>> This would work, and i don't see a way to optimize it in git-speak,
>> given that you don't want to see any extra trailing merges. [...]
> 
> The provided command actually doesn't work for me for all cases.  It
> works for the simple case of "B", but does not work for "F", because F
> saw merge H & M.  I think we need --not --first-parent, except that

Well, F was never on a separate branch, so the command returning ""
is arguably the right thing.
The example I gave
(B->[merge of subtopic]->[merged to supertopic]->[merged to master])
was the case where "--not-first-parent" wouldn't help, even if such
an option would exist.

> doesn't actually work in this case either.  However, if we get the
> full --first-parent rev-list and look for our commit, that works.
> This is incredibly painful, though.
> ----------------------------------------------------------------------
> #!/bin/sh
> TARGET=`git rev-list -n 1 $1`
> git branch -a --contains $1 | sed 's/^\** *//' | grep -v ' -> ' |
> while read br; do
>  if git rev-list --first-parent $br | grep -q "$TARGET"; then
>   echo $br
>  fi
> done
> ----------------------------------------------------------------------

And it does not work if you no longer have the branches around...

But even if you kept all the old refs, this would return
"another-topic"+"master", which is hardly the right answer.

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19 23:12         ` Artur Skawina
@ 2010-09-19 23:54           ` Seth Robertson
  2010-09-20  1:31             ` Artur Skawina
  0 siblings, 1 reply; 33+ messages in thread
From: Seth Robertson @ 2010-09-19 23:54 UTC (permalink / raw)
  To: Artur Skawina; +Cc: git


In message <4C9698C5.70607@gmail.com>, Artur Skawina writes:

On 09/20/10 00:03, Seth Robertson wrote:
>>>>>                A---B---C topic
>>>>>               /         \
>>>>>          D---E---F---G---H---I---J---K---L---M---N master
>>>>>                                   \         /
>>>>>                                    O---P---Q another-topic
>>
>>>> No, that's not what I need either.  After thinking about it more, I
>>>> think what I want is "of all merges in the ancestry path from B to
>>>> master, show only those whose first parent can't reach B."  The result
>>>> is the list of all merges that were involved in bringing B to master.
>>
>>
>>> This would work, and i don't see a way to optimize it in git-speak,
>>> given that you don't want to see any extra trailing merges. [...]
>>
>> The provided command actually doesn't work for me for all cases.  It
>> works for the simple case of "B", but does not work for "F", because F
>> saw merge H & M.  I think we need --not --first-parent, except that
>
> Well, F was never on a separate branch, so the command returning ""
> is arguably the right thing.

I'd like a command that would tell me the right branch something was
on whether it was on master or topic or whatever.  If instead of
"master" the branch was named "supertopic" and master commit AA had
child D would that make a difference?

>> doesn't actually work in this case either.  However, if we get the
>> full --first-parent rev-list and look for our commit, that works.
>> This is incredibly painful, though.
>> ----------------------------------------------------------------------
>> #!/bin/sh
>> TARGET=`git rev-list -n 1 $1`
>> git branch -a --contains $1 | sed 's/^\** *//' | grep -v ' -> ' |
>> while read br; do
>>  if git rev-list --first-parent $br | grep -q "$TARGET"; then
>>   echo $br
>>  fi
>> done
>> ----------------------------------------------------------------------

> And it does not work if you no longer have the branches around...

If something doesn't have a name I am not very interested in it (for
my purposes, your milage may vary).  Presumably the other code could be
combined with my inner loop.

>But even if you kept all the old refs, this would return
>"another-topic"+"master", which is hardly the right answer.

I'm not sure how you can figure out when a branch was first created.
We might "know" that master is older than the others, but if this
commit was on another-topic and supertopic we cannot use that
intuition..

Returning all possible branch names at least gives the user somewhere
to start and does not give them ones which are obviously insane.

					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-19 23:54           ` Seth Robertson
@ 2010-09-20  1:31             ` Artur Skawina
  2010-09-20  5:47               ` Seth Robertson
  0 siblings, 1 reply; 33+ messages in thread
From: Artur Skawina @ 2010-09-20  1:31 UTC (permalink / raw)
  To: Seth Robertson; +Cc: git

On 09/20/10 01:54, Seth Robertson wrote:
> In message <4C9698C5.70607@gmail.com>, Artur Skawina writes:
> 
> On 09/20/10 00:03, Seth Robertson wrote:
>>>>>>                A---B---C topic
>>>>>>               /         \
>>>>>>          D---E---F---G---H---I---J---K---L---M---N master
>>>>>>                                   \         /
>>>>>>                                    O---P---Q another-topic
>>>
>>>>> No, that's not what I need either.  After thinking about it more, I
>>>>> think what I want is "of all merges in the ancestry path from B to
>>>>> master, show only those whose first parent can't reach B."  The result
>>>>> is the list of all merges that were involved in bringing B to master.
>>>
>>>
>>>> This would work, and i don't see a way to optimize it in git-speak,
>>>> given that you don't want to see any extra trailing merges. [...]
>>>
>>> The provided command actually doesn't work for me for all cases.  It
>>> works for the simple case of "B", but does not work for "F", because F
>>> saw merge H & M.  I think we need --not --first-parent, except that
>>
>> Well, F was never on a separate branch, so the command returning ""
>> is arguably the right thing.
> 
> I'd like a command that would tell me the right branch something was
> on whether it was on master or topic or whatever.  If instead of
> "master" the branch was named "supertopic" and master commit AA had
> child D would that make a difference?

Like i said, "arguably". In theory, no, there is no difference. In
practice, some branches will be more long-lived than others -- and
certain conventions will apply. Hence, i think that answer /is/ the
right one, in context -- that script was specifically looking for
info on /another/ branch.

>>> doesn't actually work in this case either.  However, if we get the
>>> full --first-parent rev-list and look for our commit, that works.
>>> This is incredibly painful, though.
>>> ----------------------------------------------------------------------
>>> #!/bin/sh
>>> TARGET=`git rev-list -n 1 $1`
>>> git branch -a --contains $1 | sed 's/^\** *//' | grep -v ' -> ' |
>>> while read br; do
>>>  if git rev-list --first-parent $br | grep -q "$TARGET"; then
>>>   echo $br
>>>  fi
>>> done
>>> ----------------------------------------------------------------------
> 
>> And it does not work if you no longer have the branches around...
> 
> If something doesn't have a name I am not very interested in it (for
> my purposes, your milage may vary).  Presumably the other code could be
> combined with my inner loop.
> 
>> But even if you kept all the old refs, this would return
>> "another-topic"+"master", which is hardly the right answer.
> 
> I'm not sure how you can figure out when a branch was first created.
> We might "know" that master is older than the others, but if this
> commit was on another-topic and supertopic we cannot use that
> intuition..
> 
> Returning all possible branch names at least gives the user somewhere
> to start and does not give them ones which are obviously insane.

If you want to find out on which branch a change was committed and
"master" is right for 'F', then the "another-topic" part of that
answer is problematic -- every commit on that branch is a descendant
of 'F", and so is everything in between $common_base ('J') and master.
If you /don't/ treat master as special (ie don't treat the first
parent as special) what is then the difference vs a simple
"git branch -a --contains F"?
IOW, why would the right answer for 'F' be both 'master' and
'another-topic', but for 'B' - just 'topic'?

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-20  1:31             ` Artur Skawina
@ 2010-09-20  5:47               ` Seth Robertson
  2010-09-20  8:12                 ` Stefan Haller
  0 siblings, 1 reply; 33+ messages in thread
From: Seth Robertson @ 2010-09-20  5:47 UTC (permalink / raw)
  To: Artur Skawina; +Cc: git


In message <4C96B97D.6030209@gmail.com>, Artur Skawina writes:

    On 09/20/10 01:54, Seth Robertson wrote:

    > I'd like a command that would tell me the right branch something was
    > on whether it was on master or topic or whatever.  If instead of
    > "master" the branch was named "supertopic" and master commit AA had
    > child D would that make a difference?

    Like i said, "arguably". In theory, no, there is no difference. In
    practice, some branches will be more long-lived than others -- and
    certain conventions will apply. Hence, i think that answer /is/ the
    right one, in context -- that script was specifically looking for
    info on /another/ branch.

Only if the topic branch didn't have a merge on it.

         -AA-- subtopic
        /     \
       A---B---C topic
      /         \
 D---E---F---G---H---I---J---K---L---M---N master
                          \         /
                           O---P---Q another-topic


In the above example, the subtopic branch merge from AA to C prevents
you from finding out what branch B is on using the original script.


    > I'm not sure how you can figure out when a branch was first created.
    > We might "know" that master is older than the others, but if this
    > commit was on another-topic and supertopic we cannot use that
    > intuition..

    > Returning all possible branch names at least gives the user somewhere
    > to start and does not give them ones which are obviously insane.

    IOW, why would the right answer for 'F' be both 'master' and
    'another-topic', but for 'B' - just 'topic'?

I agree 100% that the right answer is topic for B and master for F.

I know how to get topic for B.  Finding master (and not another-topic)
for F is difficult because we have to know something that I don't know
how to get git to tell me: when another-topic branch was created.
Using git-rev-parse another-topic....master we know what commit
another-topic and master diverged, but I cannot figure out a way to
discover which branch was created at that point and which branch
pre-existed (obviously for master we know, but if this was a
supertopic branch we would not).  I thought about using merge
direction for subsequent merges as a hint, but we don't know if the
second branch has been permanently been merged or not, if there was a
K->P merge and Q-M did not happen (yet) then we would give the wrong
branch name.

If you (or anyone) can answer that question, I'll be happy to update
the script.  Otherwise getting both answers is as close as we can come.

					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-20  5:47               ` Seth Robertson
@ 2010-09-20  8:12                 ` Stefan Haller
  2010-09-20 10:58                   ` Artur Skawina
  0 siblings, 1 reply; 33+ messages in thread
From: Stefan Haller @ 2010-09-20  8:12 UTC (permalink / raw)
  To: Seth Robertson, Artur Skawina; +Cc: git

Seth Robertson <in-gitvger@baka.org> wrote:

> In message <4C96B97D.6030209@gmail.com>, Artur Skawina writes:
> 
>     On 09/20/10 01:54, Seth Robertson wrote:
> 
>     > I'd like a command that would tell me the right branch something was
>     > on whether it was on master or topic or whatever.  If instead of
>     > "master" the branch was named "supertopic" and master commit AA had
>     > child D would that make a difference?
> 
>     Like i said, "arguably". In theory, no, there is no difference. In
>     practice, some branches will be more long-lived than others -- and
>     certain conventions will apply. Hence, i think that answer /is/ the
>     right one, in context -- that script was specifically looking for
>     info on /another/ branch.
> 
> Only if the topic branch didn't have a merge on it.
> 
>          -AA-- subtopic
>         /     \
>        A---B---C topic
>       /         \
>  D---E---F---G---H---I---J---K---L---M---N master
>                           \         /
>                            O---P---Q another-topic
> 
> 
> In the above example, the subtopic branch merge from AA to C prevents
> you from finding out what branch B is on using the original script.

When you say "the original script", are you talking about Artur's
one-liner or my script?

My script gives me exactly the information I want in all cases.  For a
given command $1 and a target branch $2, it shows you all merges that
were involved in bringing $1 into $2. For example:

  Called with "B" "master", it returns H
  Called with "AA" "master", it returns C, H
    (and that's good, because for someone asking "what was AA's original
     branch?" it's not clear if he will be more interested in topic or
     sub-topic, so show him both)
  Called with "F" "master", it returns nothing

The one limitation is that the result is empty both when $1 started on
$2, and when $1 is not reachable from $2 at all, in which case it should
probably error out (like when you call it with "F" "topic").  That's
easy to add as an additional check at the beginning of the script,
though.


The script works even in cases where you have a long-running topic
branch that is occasionally brought up to date with master, like this:


         F---G---H---I---J---O---P  topic
        /       /       /         \
   A---B---C---D---E---K---L---M---N---Q master


When called with "F" "master", it returns only N, but not H or J.
Exactly what I need.  (We have this kind of history a lot in our code
base.)

You could even call the script with "C" "topic" if you wanted to (in
which case it would return H, but not J).  It's not quite clear why you
would want to though.


-- 
Stefan Haller
Berlin, Germany
http://www.haller-berlin.de/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-20  8:12                 ` Stefan Haller
@ 2010-09-20 10:58                   ` Artur Skawina
  2010-09-20 15:49                     ` Artur Skawina
  2010-09-20 18:20                     ` Find out on which branch a commit was originally made Stefan Haller
  0 siblings, 2 replies; 33+ messages in thread
From: Artur Skawina @ 2010-09-20 10:58 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Seth Robertson, git

On 09/20/10 10:12, Stefan Haller wrote:
> Seth Robertson <in-gitvger@baka.org> wrote:

>>          -AA-- subtopic
>>         /     \
>>        A---B---C topic
>>       /         \
>>  D---E---F---G---H---I---J---K---L---M---N master
>>                           \         /
>>                            O---P---Q another-topic
>>
>>
>> In the above example, the subtopic branch merge from AA to C prevents
>> you from finding out what branch B is on using the original script.
> 
> When you say "the original script", are you talking about Artur's
> one-liner or my script?
> 
> My script gives me exactly the information I want in all cases.  For a
> given command $1 and a target branch $2, it shows you all merges that
> were involved in bringing $1 into $2. For example:
> 
>   Called with "B" "master", it returns H

No, it will return both C and H, just like my one-liner; this will be
misleading, the user won't be able to figure out where 'B" came from
w/o looking at the graph, from output like:

$ git-show-merges-since B master
C..... Merge branch 'subtopic' into topic
H..... Merge branch 'topic'

The results for 'B' and 'AA' will be exactly the same.

For 'B', the 'C' merge should be omitted; skipping it because 'B'
comes in via first parent would probably work, but i can't turn that
into a one-liner right now...


On 09/20/10 07:47, Seth Robertson wrote:
> I agree 100% that the right answer is topic for B and master for F.
> 
> I know how to get topic for B.  Finding master (and not another-topic)
> for F is difficult because we have to know something that I don't know
> how to get git to tell me: when another-topic branch was created.
> Using git-rev-parse another-topic....master we know what commit
> another-topic and master diverged, but I cannot figure out a way to
> discover which branch was created at that point and which branch
> pre-existed (obviously for master we know, but if this was a
> supertopic branch we would not).  I thought about using merge
> direction for subsequent merges as a hint, but we don't know if the
> second branch has been permanently been merged or not, if there was a
> K->P merge and Q-M did not happen (yet) then we would give the wrong
> branch name.

Oh, if there would be no 'Q->M' merge and both branches would still
be "live", 'both' is certainly the right answer.

If 'another-topic' was merged into another branch (like in the example
graph) and is dead at this point, i think skipping it is the correct
decision -- there could be many such branches and presenting a long
list of candidates won't really help the user.

Given history as in the graph and a /live/ 'another-topic' -- hmm, 
if there are just a few such refs maybe showing them would be ok.

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-20 10:58                   ` Artur Skawina
@ 2010-09-20 15:49                     ` Artur Skawina
  2010-09-21  0:15                       ` Seth Robertson
  2010-09-20 18:20                     ` Find out on which branch a commit was originally made Stefan Haller
  1 sibling, 1 reply; 33+ messages in thread
From: Artur Skawina @ 2010-09-20 15:49 UTC (permalink / raw)
  To: Stefan Haller; +Cc: Seth Robertson, git

On 09/20/10 12:58, Artur Skawina wrote:
> On 09/20/10 10:12, Stefan Haller wrote:
>> Seth Robertson <in-gitvger@baka.org> wrote:
> 
>>>          -AA-- subtopic
>>>         /     \
>>>        A---B---C topic
>>>       /         \
>>>  D---E---F---G---H---I---J---K---L---M---N master
>>>                           \         /
>>>                            O---P---Q another-topic
>>>
>>>
>>> In the above example, the subtopic branch merge from AA to C prevents
>>> you from finding out what branch B is on using the original script.
>>
>> When you say "the original script", are you talking about Artur's
>> one-liner or my script?
>>
>> My script gives me exactly the information I want in all cases.  For a
>> given command $1 and a target branch $2, it shows you all merges that
>> were involved in bringing $1 into $2. For example:
>>
>>   Called with "B" "master", it returns H
> 
> No, it will return both C and H, just like my one-liner; this will be
> misleading, the user won't be able to figure out where 'B" came from
> w/o looking at the graph, from output like:
> 
> $ git-show-merges-since B master
> C..... Merge branch 'subtopic' into topic
> H..... Merge branch 'topic'
> 
> The results for 'B' and 'AA' will be exactly the same.
> 
> For 'B', the 'C' merge should be omitted; skipping it because 'B'
> comes in via first parent would probably work, but i can't turn that
> into a one-liner right now...

Yeah, that was it; the script below will correctly handle not only
the simple example above, but also some real cases. 

Usage: git-find-branch-for <rev> [long-lived-branch]

Returns some merge commits, making it easier to find out from which
branch a change originated. Returns nothing if it did not find an
interesting merge all the way up to long-lived-branch (which defaults
to "master")

Example, using git.git:

$ time ../../../stefans-script bac80370817
4fa088209c81845e73756a4173a8c954e25958d2 Merge branch 'jk/run-command-use-shell'
225f78c817755bebff91629cc525a258cf60eaea Merge branch 'master' of git://repo.or.cz/alt-git into jn/autodep
037c43c68e220739e690540de89a6d5835fefe73 Merge remote branch 'ko/master' into jc/read-tree-cache-tree-fix
1m23.271s user   0m2.173s system   1m26.389s elapsed   98.90% CPU

$ time ../../../git-find-branch-for bac80370817                             
4fa08820    Merge branch 'jk/run-command-use-shell'        * jk/run-command-use 1263743895
225f78c8    Merge branch 'master' of git://repo.or.cz/alt-git into jn/autodep   1264500524
037c43c6    Merge remote branch 'ko/master' into jc/read-tree-cache-tree-fix    1278615350
0m0.270s user   0m0.017s system   0m0.287s elapsed   99.87% CPU
$

So it's also a little bit faster.
Received very little testing, i only tried it on a few commits, other
than the example from this thread, but so far seems to do the right
thing for all of them.
Unpikifying is left as an exercise for the user. ;)

artur

------------------------------------------------------------------------------
#! /usr/bin/env pike
// git-find-branch-for <rev> [long-lived-branch]
//    Probably needs pike7.8
#define die(a...) exit(1, "Aborting; %s"+a)

string run(string ... cmdline) {
   mapping r;
   mixed e = catch { r = Process.run( ({@cmdline}) ); };
   if (e || r["exitcode"])
      die("", e?e:r["stderr"]);
   return r["stdout"];
}

mapping commits = ([]);

array parsecommits(string from, string to) {
   array res = ({});
   string id;
   string gitout = run("git", "rev-list", "--format=raw",  "--ancestry-path",
                                          "--date-order", from+".."+to);
   array lines = gitout/"\n";

   foreach (lines, string line) {
      array words = line/" ";
      if (words[0]=="commit") {
         id = words[1][0]!='-' ? words[1] : words[1][1..];
	 commits[id] = ([]);
	 res += ({id});
      }
      commits[id][words[0]] += words[1..];
   }
   return res;
}

int ismerge(string id) {
   return commits[id]["parent"] && sizeof(commits[id]["parent"])>1;
}

mapping desc = ([]);

int main(int argc, array argv) {
   argv[1] = (run("git", "rev-parse", argv[1])/"\n")[0];
   if (argc==2)
      argv += ({"master"});
   argv[2] = (run("git", "rev-parse", argv[2])/"\n")[0];
   array merges = parsecommits(argv[1], argv[2]);
   merges = reverse(merges);
   desc[argv[1]] = 1;
   foreach (merges, string id) {
      if (commits[id]["parent"])
         foreach (commits[id]["parent"], string parent)
            if (desc[parent])
        	desc[id] = 1;
      if (ismerge(id))
         if (!desc[commits[id]["parent"][0]]) {
	    int comtime = (int)commits[id]["committer"][-2];
	    comtime += (int)commits[id]["committer"][-1]/100*60*60;
            write("%.8s %.70s %d\n", id, commits[id][""]*" ", comtime );
	 }
   }
}
------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-20 10:58                   ` Artur Skawina
  2010-09-20 15:49                     ` Artur Skawina
@ 2010-09-20 18:20                     ` Stefan Haller
  1 sibling, 0 replies; 33+ messages in thread
From: Stefan Haller @ 2010-09-20 18:20 UTC (permalink / raw)
  To: Artur Skawina; +Cc: Seth Robertson, git

Artur Skawina <art.08.09@gmail.com> wrote:

> >>          -AA-- subtopic
> >>         /     \
> >>        A---B---C topic
> >>       /         \
> >>  D---E---F---G---H---I---J---K---L---M---N master
> >>                           \         /
> >>                            O---P---Q another-topic
> >>
> >>
> >> In the above example, the subtopic branch merge from AA to C prevents
> >> you from finding out what branch B is on using the original script.
> >
> >   Called with "B" "master", it returns H
> 
> No, it will return both C and H, just like my one-liner;

Right, there was a bug in my script: it doesn't work if B is a direct
parent of the next merge. (For A, it would correctly return only H.)  To
fix that, you'd need this version:

#!/bin/sh

git rev-list --ancestry-path --merges --reverse "$1".."${2-master}" \
  | while read ref
do
  if [ "$1" != "$ref"^ -a -z "$(git rev-list --ancestry-path "$1".."$ref"^)" ]
  then
    git --no-pager log -1 --pretty=oneline "$ref"
  fi
done

But of course, since your version is so much faster, I'll no longer
bother with mine.  Thanks!

-Stefan


-- 
Stefan Haller
Berlin, Germany
http://www.haller-berlin.de/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-20 15:49                     ` Artur Skawina
@ 2010-09-21  0:15                       ` Seth Robertson
  2010-09-21  2:12                         ` Artur Skawina
  0 siblings, 1 reply; 33+ messages in thread
From: Seth Robertson @ 2010-09-21  0:15 UTC (permalink / raw)
  To: Artur Skawina; +Cc: Stefan Haller, git


In message <4C9782A3.5010005@gmail.com>, Artur Skawina writes:

    Received very little testing, i only tried it on a few commits, other
    than the example from this thread, but so far seems to do the right
    thing for all of them.

I've discovered an error case in your pike script's logic (as and if I
understand it).  If there are multiple children of the commit in
question and those two children both merge onto the target branch, the
path your program prints is incorrect (specifically, for reference B
it prints D and then G--the correct answer is G only or a least D+H).
It does not check to see whether a specific reachable merge commit is
reachable by the path you have started to print.

----master-----------G------H
                    /      /
                    |     /
 --A-------D-----------F-
          /         |
 ----B---C          |
      \             |
       ----------E--/

    Unpikifying is left as an exercise for the user. ;)

I've converted it to perl and it now handles both your problem (which
I now understand, I was distracted by the subject line) and mine
(which I now better understand includes yours as well--we use --rebase
a lot so don't have many unnamed branches).  I'm also being annoyed at
git's default merge --ff option which causes the wrong branch to be
labeled with the branch name.

Of course it still suffers from reporting branches created after the
reference you are interested in was created.

					-Seth Robertson

git://github.com/SethRobertson/git-what-branch.git

----------------------------------------------------------------------
#!/usr/bin/perl
#
# Tell us what preferred branch a commit was made on and if has not
# been made on any preferred branch, the earliest path the commit got
# onto a named branch.
#
# Preferred meaning ignoring branches that are a descendant due to a
# merge, close to the answer you would have gotten if you had asked
# the question at the moment the commit/tag was made.
#
# If I am on a release branch and tag a commit, if I ask that question
# I should be told the name of the release branch.  If I later merge
# onto master and ask that question, being told that the tag was also
# made on master is disingenious.  master is a descendant, but the tag
# was not made on master.
#
# Thanks to Artur Skawina for his assistance in developing some
# of the algorithms used by this script.
#
# License: GPL v2
# Copyright (c) 2010 Seth Robertson
#
use warnings;
no warnings "uninitialized";
use Getopt::Long;
use strict;

my $USAGE="$0: [--allref] [--all] [--quiet] [--reference-branch=branchname] [--reference=reference] <commit-hash/tag>...

--allref
	Consider even remote branches as candidates for the branch a
	reference is on

--all
	Print all reachable branch names (and merge paths)

--quiet
	Print only the branch names, not the merge paths

--reference-branch <branchname>
	The command line arguments/reference are searched to see if
	they can reach this branch.

--reference <hash|tag>
	Specify a particular commit you which you want to
	know how the commit in question was reached
";

my(%OPTIONS);
Getopt::Long::Configure("bundling", "no_ignore_case", "no_auto_abbrev", "no_getopt_compat", "require_order");
GetOptions(\%OPTIONS, 'a|allref', 'all', 'quiet', 'debug', 'reference-branch=s', 'reference=s', 'verbose|v+') || die $USAGE;

my ($OPT_A);
$OPT_A="-a" if ($OPTIONS{'a'});

if ( $#ARGV < 0 )
{
    print STDERR $USAGE;
    exit(2);
}

my ($MULTI);
$MULTI=1 if ( $#ARGV > 0 );




########################################
#
# Describe a hash if necessary
#
sub describep($)
{
  my ($ref) = @_;

  if ($ref =~ /^[0-9a-f]{40}$/)
  {
    my $newref;
    chomp($newref = `git describe $ref`);
    $ref = $newref if ($newref && $? == 0);
  }
  $ref;
}



########################################
#
# Find shortest path through a dag
# Return array of shortest path
#
sub find_shortest($$$$);
sub find_shortest($$$$)
{
  my ($id,$target,$tree,$mark) = @_;

  print STDERR "Looking at node $id\n" if ($OPTIONS{'debug'});

  while ($id ne $target)
  {
    # Is this a merge commit?
    if ($#{$tree->{$id}->{'parent'}} > 0)
    {
      # Is the first parent not a descendant?
      if (!$mark->{$tree->{$id}->{'parent'}->[0]})
      {
	my (@minp);
	my ($mindef);

	# See which parent is the best connected
	foreach my $parent (@{$tree->{$id}->{'parent'}})
	{
	  next unless $mark->{$parent};

	  my (@tmp) = find_shortest($parent,$target,$tree,$mark);

	  if (!$mindef || $#minp > $#tmp)
	  {
	    @minp = @tmp;
	    $mindef = 1;
	  }
	}
	unshift(@minp,$id);
	return(@minp);
      }
    }

    $id = $tree->{$id}->{'parent'}->[0];
  }
  ();
}


foreach my $f (@ARGV)
{
  print "Looking for $f\n++++++++++++++++++++++++++++++++++++++++\n" if ($MULTI);

  # Translate into a commit hash
  my ($TARGET)=`git rev-list -n 1 $f 2>/dev/null`;
  die "Unknown reference $f\n" if ($?);
  chomp($TARGET);

  my (@first,@second);

  if ($OPTIONS{'reference'})
  {
    my $tmp = `git rev-list -n 1 $OPTIONS{'reference'} 2>/dev/null`;
    die "Unknown --reference $OPTIONS{'reference'}\n" if ($?);
    chomp($tmp);
    @first = ($tmp);
  }
  else
  {
    # Generate first pass list of candidate branches
    @first = grep(s/^\*?\s+// && s/\n// && !/ -\> / && (!$OPTIONS{'reference-branch'} || $OPTIONS{'reference-branch'} eq $_),`git branch $OPT_A --contains $f`);

    if ($#first < 0)
    {
      my $msg = "any named branch";
      $msg = "any local named branch" unless ($OPTIONS{'a'});
      $msg = "branch $OPTIONS{'reference-branch'}" if ($OPTIONS{'reference-branch'});
      die "Commit $f has not merged onto $msg yet\n";
    }
  }

  # Shortcut if we might only need direct commit branches
  if (!$OPTIONS{'all'})
  {
    # Look for merge intos to exclude
    foreach my $br (@first)
    {
      # Exclude branches that this commit was merged into
      push(@second,$br) if (grep(/$TARGET/,`git rev-list --first-parent $br`));
    }
  }

  if ($#second >= 0)
  {
    # If branch was subsequently forked via `git branch <old> <new>`
    # we might have multiple answers.  Only one is right, but we
    # cannot figure out which is the privledged branch because the
    # branch creation information is not preserved.

    print join("\n",@second)."\n";
  }
  else
  {
    # Commit is on an anonymous branch, find out where it merged

    my (%brtree,%min);
    foreach my $br (@first)
    {
      my (%commits,@commits);
      my $SOURCE = `git rev-list -n 1 $br 2>/dev/null`;
      die "Cannot find branch reference.  Huh?\n" if ($?);
      chomp($SOURCE);
      print STDERR "Checking branch $br\n" if ($OPTIONS{'debug'});

      # Discover all "ancestry-path" commits between target and branch
      my $cmd = qq^git rev-list --ancestry-path --date-order --format=raw "$TARGET".."$br"^;
      my ($commit);
      foreach my $line (`$cmd`)
      {
	my (@f) = split(/\s+/,$line);
	if ($f[0] eq "commit")
	{
	  $commit = $f[1];
	  $commit =~ s/^-//;	# I have never seen this myself, but Artur Skawina wrote code to defend against it
	  unshift(@commits,$commit);
	}
	if ($f[0] eq "parent")
	{
	  push(@{$commits{$commit}->{'parent'}},$f[1]);
	}
	if ($f[0] eq "committer")
	{
	  $commits{$commit}->{'committime'} = $f[$#f-1];
	}
      }

      print STDERR "Found $#commits+1\n" if ($OPTIONS{'debug'});

      my (@path);

      # Go through commit list (in forward chonological order)
      my (%mark,$cnt);
      $mark{$TARGET} = ++$cnt;
      foreach my $id (@commits)
      {
	next unless $commits{$id}->{'parent'};

	# Check to see if this commit is actually a descent of $TARGET
	if (grep($mark{$_},@{$commits{$id}->{'parent'}}))
	{
	  $mark{$id} = ++$cnt;
	}

	# Is this a merge commit?
	if ($#{$commits{$id}->{'parent'}} > 0)
	{
	  # Is the first parent not a descendant? (earliest merge)
	  if (!$mark{$commits{$id}->{'parent'}->[0]})
	  {
	    push(@path,$id);
	  }
	}
      }

      # Check to make sure we have gone from TARGET or SOURCE via parents
      if (!$mark{$SOURCE})
      {
	# Not connected
	next;
      }

      print STDERR "Found $#path+1 initial path entries\n" if ($OPTIONS{'debug'});

      if ($#path >= 0)
      {
	my $id = $path[$#path];
	@path = find_shortest($id,$TARGET,\%commits,\%mark);
	$brtree{$br}->{'path'} = \@path;
	$brtree{$br}->{'cnt'} = $#path;
	$brtree{$br}->{'tstamp'} = $commits{$id}->{'committime'};

	if ($OPTIONS{'all'})
	{
	  if ($OPTIONS{'quiet'})
	  {
	    print "$br\n";
	  }
	  else
	  {
	    print "* $TARGET first merged onto $br using the following path:\n";
	    my $last = describep($TARGET);
	    foreach my $mp (@{$brtree{$br}->{'path'}})
	    {
	      my $newm = describep($mp);
	      print "  $last merged up at $newm (@{[scalar(localtime($commits{$mp}->{'committime'}))]})\n";
	      $last = $newm;
	    }
	    print "  $last is on $br\n";
	  }
	}
	else
	{
	  if (!defined($min{'tstamp'}) || $min{'tstamp'} > $brtree{br}->{'tstamp'})
	  {
	    %min = %{$brtree{$br}};
	    $min{'br'} = $br;
	    $min{'commits'} = \%commits;
	  }
	}
      }
      else
      {
	if ($OPTIONS{'all'})
	{
	  print "$TARGET is on $br\n";
	}
	else
	{
	  print "$br\n";
	}
	$min{'tstamp'} = 0;
	delete($min{'br'});
      }
    }

    if (!$OPTIONS{'all'})
    {
      if ($min{'br'})
      {
	if ($OPTIONS{'quiet'})
	{
	  print "$min{'br'}\n";
	}
	else
	{
	  print "$f first merged onto $min{'br'} using the following minimal path:\n";
	  my $last = describep($TARGET);
	  foreach my $br (@{$min{'path'}})
	  {
	    my $newm = describep($br);
	    print "  $last merged up at $newm (@{[scalar(localtime($min{'commits'}->{$br}->{'committime'}))]})\n";
	    $last = $newm;
	  }
	  print "  $last is on $min{'br'}\n";
	}
      }
      else
      {
	print "Could not find $f connected anywhere\n" unless defined($min{'tstamp'});
      }
    }
  }
  print "----------------------------------------\n" if ($MULTI);
}

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-21  0:15                       ` Seth Robertson
@ 2010-09-21  2:12                         ` Artur Skawina
  2010-09-22 16:35                           ` ANNOUNCE git-what-branch (was Re: Find out on which branch a commit was originally made) Seth Robertson
  0 siblings, 1 reply; 33+ messages in thread
From: Artur Skawina @ 2010-09-21  2:12 UTC (permalink / raw)
  To: Seth Robertson; +Cc: Stefan Haller, git

On 09/21/10 02:15, Seth Robertson wrote:
> 
> I've discovered an error case in your pike script's logic (as and if I
> understand it).  If there are multiple children of the commit in
> question and those two children both merge onto the target branch, the
> path your program prints is incorrect (specifically, for reference B
> it prints D and then G--the correct answer is G only or a least D+H).
> It does not check to see whether a specific reachable merge commit is
> reachable by the path you have started to print.
> 
> ----master-----------G------H
>                     /      /
>                     |     /
>  --A-------D-----------F-
>           /         |
>  ----B---C          |
>       \             |
>        ----------E--/

I haven't checked, but I expect it to print exactly 'D' and 'G'.
'H' isn't interesting, as both parents already contain 'B'.
Yes, 'D' could be omitted, but knowing where else 'B' also
appeared /can/ be useful (and figuring out if it's safe to skip
'D' would be more expensive).

>     Unpikifying is left as an exercise for the user. ;)
> 
> I've converted it to perl and it now handles both your problem (which

I wasn't exactly thinking of perl when i wrote that... :)

> Of course it still suffers from reporting branches created after the
> reference you are interested in was created.

Well, at least git-find-branch-for, shows (some) merges _to_ other
(topic/remote) branches, but after browsing the kernel history
for a while i'm a bit surprised -- this causes significantly less
problems than i expected.

I haven't looked at your script, so i'm not sure what exactly it
tries to do, but i ran a quick test, using the kernel tree:

$ time git-find-branch-for 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 
84e48b6d64fd Merge of master.kernel.org:/home/rmk/linux-2.6-rmk.git   050503 22:27
bfd4bda097f8 Merge with master.kernel.org:/pub/scm/linux/kernel/git/t 050505 12:59
325a479c4c11 Merge with temp tree to get David's gdb inferior calls p 050517 22:53
ad34ea2cc384 merge by hand - fix up rejections in Documentation/DocBo 050520 20:27
0m10.549s user   0m0.713s system   0m10.963s elapsed   102.74% CPU
$
$ time git-what-branch 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto v2.6.32.n using the following minimal path:
  v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc4-39-gad34ea2 (Fri May 20 22:27:44 2005)
  v2.6.12-rc4-39-gad34ea2 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May  5 14:59:37 2005)
  v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Wed May  4 00:27:24 2005)
  v2.6.12-rc3-461-g84e48b6 is on v2.6.32.n
18m29.771s user   0m29.681s system   18m4.897s elapsed   105.03% CPU
$

Results are similar, that one extra merge i'll have to take a look at
later, but the cost difference...

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* ANNOUNCE git-what-branch (was Re: Find out on which branch a commit was originally made)
  2010-09-21  2:12                         ` Artur Skawina
@ 2010-09-22 16:35                           ` Seth Robertson
  2010-09-22 20:27                             ` Artur Skawina
  0 siblings, 1 reply; 33+ messages in thread
From: Seth Robertson @ 2010-09-22 16:35 UTC (permalink / raw)
  To: Artur Skawina; +Cc: Stefan Haller, git


In message <4C981475.10404@gmail.com>, Artur Skawina writes:

    $ time git-what-branch 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
    1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto v2.6.32.n using the following minimal path:
      v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc4-39-gad34ea2 (Fri May 20 22:27:44 2005)
      v2.6.12-rc4-39-gad34ea2 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May  5 14:59:37 2005)
      v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Wed May  4 00:27:24 2005)
      v2.6.12-rc3-461-g84e48b6 is on v2.6.32.n
    18m29.771s user   0m29.681s system   18m4.897s elapsed   105.03% CPU

I found two minor bugs in my script which caused it to return something
other than the most optimal path in all cases.  I then got crazy and
added a --date-order and --topo-order -- the former orders paths by
commit date and the latter orders paths by the number of merges that
took place (and then by commit date) and then path summarization if
multiple branches were obtained through the same path.

    Results are similar, that one extra merge i'll have to take a look at
    later, but the cost difference...

As we discussed privately, the cost difference is because instead of
looking at just one branch, it is looking at 150+ branches.  If you
use --reference-branch to specify the one branch you are looking at,
it takes a much more reasonable 15-20 seconds.  Likewise if you select
a commit more recent than 2005, the number of branches that it could
apply to goes down and the command runs faster.

Also in my most recent version I was able to find an even shorter path
(two merges to master).

I have cleaned everything up and made a formal release out of it.

It is available at:  http://github.com/SethRobertson/git-what-branch

					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: ANNOUNCE git-what-branch (was Re: Find out on which branch a commit was originally made)
  2010-09-22 16:35                           ` ANNOUNCE git-what-branch (was Re: Find out on which branch a commit was originally made) Seth Robertson
@ 2010-09-22 20:27                             ` Artur Skawina
  2010-09-22 23:26                               ` Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch) Seth Robertson
  0 siblings, 1 reply; 33+ messages in thread
From: Artur Skawina @ 2010-09-22 20:27 UTC (permalink / raw)
  To: Seth Robertson; +Cc: Stefan Haller, git

On 09/22/10 18:35, Seth Robertson wrote:
> looking at just one branch, it is looking at 150+ branches.  If you
> use --reference-branch to specify the one branch you are looking at,
> it takes a much more reasonable 15-20 seconds.  Likewise if you select

This started in a thread about locating dead topic branches, but what
you want is something slightly different, hence the confusion. 
AFAIUI it now, your case is basically this: you have several
independently developed topic (or side-) branches, which are
periodically merged into a master branch, the side branches
themselves are also merging 'master' to receive changes happening
elsewhere. So the graph could look like this:

 m-> m -> m -> m -> m -> m -> m ->   master
  \        \       /         /
   b -> b -> b -> b -> b -> b ->    side-branch#1

Ditto for the other n side-branches. 

What you're asking for is: given commit C and a list of several side
branches, tell me where (ie on which branch) this commit originated.

Two things make the above trivial history a bit more complicated.
A) one side-branch can merge another, and build on top of changes that
   are not yet available on 'master'; the result can then appear in master
   via either one or both paths. This is why showing when and how a change
   became visible on every side branch can be interesting.
B) when a side branch does not contain any new changes, but is made uptodate
   wrt master, the resulting history could end up like this:

 m-> m -> m -> m -> m -> m -> m ->   master
  \           /      \       /
   b -> b -> b        c ->  c ->    side-branch#1
    
   What happened was -- git "optimized" the simple merge away, turning it
   into a fast-forward, saving one merge commit, but loosing the link
   connecting the 'c' and 'b' parts of 'side-branch#1'.   

Do you (anybody) happen to know a public repo, w/ history as above, ie
w/ more then one long-lived branch that has seen some fast-forwards? 
I wonder how reliable recovering the missing link would be...

And there's no reason why this operation should take ~20 minutes, even
for the randomly chosen, but real, worst case. But finding a good repo
to test w/ would take longer than writing the code...

artur

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-22 20:27                             ` Artur Skawina
@ 2010-09-22 23:26                               ` Seth Robertson
  2010-09-23 13:14                                 ` Stephen Bash
  0 siblings, 1 reply; 33+ messages in thread
From: Seth Robertson @ 2010-09-22 23:26 UTC (permalink / raw)
  To: Artur Skawina; +Cc: Stefan Haller, git


In message <4C9A66AF.5000302@gmail.com>, Artur Skawina writes:

    This started in a thread about locating dead topic branche

Isn't that pretty easy to do?  `git fsck --unreachable master | grep
commits`?  Post-processing that to assemble branches would seem to be
fairly simple.

But yes, I wanted something completely different.  Something more
like: if a bug was introduced in commit X, what releases or branches
has it contaminated (or more positively, if a feature was introduced,
where was it made available).  The simple case is figuring out on
which branch a commit was originally made.

I was unhappy when I realized that another way code could get out was
through cherry-picks, and that there doesn't seem any non-brute force
(computing checksums of patches for every patch in the tree) method to
discover them.

    Two things make the above trivial history a bit more complicated.
    A) one side-branch can merge another, and build on top of changes that
       are not yet available on 'master'; the result can then appear in master
       via either one or both paths. This is why showing when and how a change
       became visible on every side branch can be interesting.

Quite.  I encountered this a few different ways and even when I fixed
it during the reverse parse, I failed to learn my lesson and it was a
problem during the forward parse.  I think the latest version is
fairly bullet-proof.

    B) when a side branch does not contain any new changes, but is
       made uptodate wrt master, the resulting history could end up
       like this:

     m-> m -> m -> m -> m -> m -> m ->   master
      \           /      \       /
       b -> b -> b        c ->  c ->    side-branch#1

       What happened was -- git "optimized" the simple merge away, turning it
       into a fast-forward, saving one merge commit, but loosing the link
       connecting the 'c' and 'b' parts of 'side-branch#1'.

    Do you (anybody) happen to know a public repo, w/ history as above, ie
    w/ more then one long-lived branch that has seen some fast-forwards?
    I wonder how reliable recovering the missing link would be...

I have a real (non-public, sorry) tree that did something approaching
this:

->m->m->m->m->m---------m
       /     /         /
b->b->b->b->b------b->b->
 \     \     \    /
  t->t->t->t->t->t

However, due to fast-forwarding, it was turned into something like this:

->m->m->m->m->m---------m
       /     /         /
b->?->?->?->?------b->b->
 \     \     \    /
  t->t->t->t->t->t
  b  b  b  b  b  b

I don't think there is any way to figure out what happened given git's
available information.

I was just saying on #git a few hours ago, though, that I think git
needed a tree anonymizing program.  As long as one does not go
overboard, it doesn't seem too difficult.  That probably means I just
have not thought about the problem hard enough.  Of course, it would
only replicate what is, not how you got there.

    And there's no reason why this operation should take ~20 minutes, even
    for the randomly chosen, but real, worst case. But finding a good repo
    to test w/ would take longer than writing the code...

It only takes 8 seconds per test on the linux kernel, which all things
considered is rather fast.  The real problem is that each test is
treated independently.  If someone got the complete history of the
project and built a tree out of it, it would be extremely fast to run
additional tests even ignoring the obvious optimiziations of not
researching known paths.

The question is, will this functionality be needed often enough to
spend the time necessary to optimize it?


					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-22 23:26                               ` Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch) Seth Robertson
@ 2010-09-23 13:14                                 ` Stephen Bash
  2010-09-23 13:26                                   ` Ævar Arnfjörð Bjarmason
  2010-09-23 14:27                                   ` Seth Robertson
  0 siblings, 2 replies; 33+ messages in thread
From: Stephen Bash @ 2010-09-23 13:14 UTC (permalink / raw)
  To: Seth Robertson; +Cc: Stefan Haller, git, Artur Skawina

----- Original Message -----
> From: "Seth Robertson" <in-gitvger@baka.org>
> To: "Artur Skawina" <art.08.09@gmail.com>
> Cc: "Stefan Haller" <lists@haller-berlin.de>, git@vger.kernel.org
> Sent: Wednesday, September 22, 2010 7:26:19 PM
> Subject: Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
>
> ... I wanted something completely different. Something more
> like: if a bug was introduced in commit X, what releases or branches
> has it contaminated (or more positively, if a feature was introduced,
> where was it made available). The simple case is figuring out on
> which branch a commit was originally made.

Wait... When you restate the problem that way, isn't git-{branch,tag} --contains the right answer?  I'm curious how you (and others) would differentiate the approaches...

If I were to frame this discussion, I think the value of git-what-branch is the ability to extract the branch name that a commit was created on.  In many environments the branch name may be useless (see the i18n example earlier in this discussion), but at least in our corporate environment, branches (especially those that are going to merge into mainline development) are named very consistently.  So in our situation the branch name can produce information that may not be captured in the standard reporting products (branch names transform into conventional tag names, branch names imply a lead developer, branch names spur developers' memories, ...).

Stephen

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-23 13:14                                 ` Stephen Bash
@ 2010-09-23 13:26                                   ` Ævar Arnfjörð Bjarmason
  2010-09-23 21:32                                     ` Artur Skawina
  2010-09-23 14:27                                   ` Seth Robertson
  1 sibling, 1 reply; 33+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-09-23 13:26 UTC (permalink / raw)
  To: Stephen Bash; +Cc: Seth Robertson, Stefan Haller, git, Artur Skawina

On Thu, Sep 23, 2010 at 13:14, Stephen Bash <bash@genarts.com> wrote:
> ----- Original Message -----
>> From: "Seth Robertson" <in-gitvger@baka.org>
>> To: "Artur Skawina" <art.08.09@gmail.com>
>> Cc: "Stefan Haller" <lists@haller-berlin.de>, git@vger.kernel.org
>> Sent: Wednesday, September 22, 2010 7:26:19 PM
>> Subject: Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
>>
>> ... I wanted something completely different. Something more
>> like: if a bug was introduced in commit X, what releases or branches
>> has it contaminated (or more positively, if a feature was introduced,
>> where was it made available). The simple case is figuring out on
>> which branch a commit was originally made.

> Wait... When you restate the problem that way, isn't
> git-{branch,tag} --contains the right answer?  I'm curious how you
> (and others) would differentiate the approaches...

git-{branch,tag} *is* the right answer, the problem here was that the
original reporter wanted to *delete* the original branch, or otherwise
not make it available, but still find out what it was.

The workaround is to walk the tree from a merge commit, but I think a
better solution is to just push the refs to your topic branches
somewhere and keep them in an archive/ namespace. Then if you need to
go digging you can always add the archive as a remote and go
git-{branch,tag} --contains.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-23 13:14                                 ` Stephen Bash
  2010-09-23 13:26                                   ` Ævar Arnfjörð Bjarmason
@ 2010-09-23 14:27                                   ` Seth Robertson
  1 sibling, 0 replies; 33+ messages in thread
From: Seth Robertson @ 2010-09-23 14:27 UTC (permalink / raw)
  To: Stephen Bash; +Cc: Stefan Haller, git, Artur Skawina


In message <32741263.335615.1285247653984.JavaMail.root@mail.hq.genarts.com>, S
tephen Bash writes:

    ----- Original Message -----
    > From: "Seth Robertson" <in-gitvger@baka.org>
    > To: "Artur Skawina" <art.08.09@gmail.com>
    > Cc: "Stefan Haller" <lists@haller-berlin.de>, git@vger.kernel.org
    > Sent: Wednesday, September 22, 2010 7:26:19 PM
    > Subject: Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
    >
    > ... I wanted something completely different. Something more
    > like: if a bug was introduced in commit X, what releases or branches
    > has it contaminated (or more positively, if a feature was introduced,
    > where was it made available). The simple case is figuring out on
    > which branch a commit was originally made.

    Wait... When you restate the problem that way, isn't
    git-{branch,tag} --contains the right answer?  I'm curious how you
    (and others) would differentiate the approaches...

Oh, it is, don't get me wrong.  I actually use `git-branch --contains`
in the script to generate my candidate list. This doesn't solve the
cherry-pick problem, but I don't solve that either (yet).  I found it
difficult to verbalize exactly why this was needed--I know I have
needed it in the past which was why I pounced on the thread and used
the ideas to write git-what-branch
http://github.com/SethRobertson/git-what-branch

    If I were to frame this discussion, I think the value of
    git-what-branch is the ability to extract the branch name that a
    commit was created on.  In many environments the branch name may
    be useless (see the i18n example earlier in this discussion), but
    at least in our corporate environment, branches (especially those
    that are going to merge into mainline development) are named very
    consistently.  So in our situation the branch name can produce
    information that may not be captured in the standard reporting
    products (branch names transform into conventional tag names,
    branch names imply a lead developer, branch names spur developers'
    memories, ...).

Exactly.  The ability to see if a commit was born on a branch or what
branch it was merged to first is what is most important (anonymous
branches do exist even if you try to use --rebase consistently) so the
ability to find which branch it merged into first is also important.
This is the default operating mode of git-what-branch.

To a lesser extent, fornensics to help understanding how a commit
merged into a specific target may also be interesting.  It would be
even nicer if we could express a path of interest to gitk so that you
could have that specific path highlighted in a `gitk --all` output.

Hmm.  Path/commit highlighting would be a nice feature in gitk no
matter what.  --highlight-stdin to highlight specific commits (and
ideally an algorithm to allow the connecting arcs for adjancent
commits to be highlighted.  There is already an interestedin hammer
Also being able to highlight specific commits at runtime (probably a
different color) and potentially enter a commit note would be pretty
cool as well.  Unfortunately I have a different skill-set.

					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-23 13:26                                   ` Ævar Arnfjörð Bjarmason
@ 2010-09-23 21:32                                     ` Artur Skawina
  2010-09-24  1:33                                       ` Artur Skawina
  2010-09-24 20:57                                       ` Seth Robertson
  0 siblings, 2 replies; 33+ messages in thread
From: Artur Skawina @ 2010-09-23 21:32 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Stephen Bash, Seth Robertson, Stefan Haller, git

On 09/23/10 15:26, Ævar Arnfjörð Bjarmason wrote:
> On Thu, Sep 23, 2010 at 13:14, Stephen Bash <bash@genarts.com> wrote:
>>> From: "Seth Robertson" <in-gitvger@baka.org>
>>> ... I wanted something completely different. Something more
>>> like: if a bug was introduced in commit X, what releases or branches
>>> has it contaminated (or more positively, if a feature was introduced,
>>> where was it made available). The simple case is figuring out on
>>> which branch a commit was originally made.
> 
>> Wait... When you restate the problem that way, isn't
>> git-{branch,tag} --contains the right answer?  I'm curious how you
>> (and others) would differentiate the approaches...
> 
> git-{branch,tag} *is* the right answer, the problem here was that the
> original reporter wanted to *delete* the original branch, or otherwise
> not make it available, but still find out what it was.
> 
> The workaround is to walk the tree from a merge commit, but I think a
> better solution is to just push the refs to your topic branches
> somewhere and keep them in an archive/ namespace. Then if you need to
> go digging you can always add the archive as a remote and go
> git-{branch,tag} --contains.

While this was my initial suggestion too, there are several valid reasons
for wanting such functionality. One is obviously to ease adaptation for 
users switching from other vcses, where branches are much more "special".
Another is that maintaining fine enough granularity in tag/branch naming
may not be that easy, not to mention the namespace clutter that causes and
that large scale omissions are practically impossible to fix retroactively.

But that's not all, consider:

$ time git-show-merge-path 0c357544b0d `git for-each-ref refs/remotes/origin --format='%(refname)'| sed -e 's,refs/remotes/,,'`
f88bdb1c315a M: 'ab/test' => next                                     100818 21:07
# Merged into origin/next
a2c6726417db M: 'ab/test-2'                                           100904 15:15
# Merged into origin/master, origin/HEAD and origin/pu
# Not reachable from origin/html, origin/man, origin/maint and origin/todo
0m0.333s user   0m0.010s system   0m0.355s elapsed   96.82% CPU

$ time git branch -r --contains 0c357544b0d
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/next
  remotes/origin/pu
0m0.283s user   0m0.013s system   0m0.303s elapsed   97.84% CPU
$

both commands have approximately the same cost, except the first one gives you
much more information.

Or, using the kernel repo: [1]

$ time git-show-merge-path 86ab04c8c1df51df master release  
b1bc81a0ef86 M: 'master'@$KO/linville/wireless-next-2.6               090607 11:24
36432dae73cf M: 'master'@$KO/davem/net-next-2.6                       090611 14:00
2ed0e21b30b5 M: $KO/davem/net-next-2.6                                090615 16:40
# Merged into release and master
0m3.056s user   0m0.207s system   0m3.154s elapsed   103.46% CPU
$

Script below; w/ one or two args works like the previous git-find-branch-for,
except it's ~two times faster for expensive queries and does that silly five 
old branch request in <13s, for *all* 150 heads; <10s for master alone; also
this one won't show extra merges that happened after the commit arrived on the
branch. When ran w/ more then one branch name, will print the merge points
and/or unreachability info for all of them, as in the above git.git example.

There's still a bug in there somewhere; finding it before blindly transforming
it into perl might be a good idea ;) I'll fix it when i'll encounter it in .rl,
right now i don't remember the random commit (in git.git) which confused it...
Still no ff-detection, mostly due to lack of (real) test case.

artur

[1] yes, 36432dae73cf could be omitted, but i can't convince myself that it
/should/ be. Implementing the filtering would be simple and cheap, but i think
i want to know that another path to master exists.


---------------------------------------------------------------------------------
#! /usr/bin/env pike
// git-show-merge-path <rev> [long-lived-branch(es)]
// v. 0.99
// Will show all external merge commits starting at <rev> until
// this commit appears on the specified branches. When that happens
// "# Merged into <branchlist>" is printed. If <rev> is still
// unreachable from some of the branches then the search continues.
// If at least one of the branches does not contain <rev> then $0
// can and will print *all* merges (ie it won't stop at the last
// of the given branches containing this commit), followed by 
// "# Not reachable from <branchlist>". This is a feature (can be
// used to find leaks outside of the given branches).
//
#define die(a...) exit(1, "Aborting; %s"+a)

string run(string ... cmdline) {
#if __REAL_MAJOR__<7 || __REAL_MAJOR__==7 && __REAL_MINOR__<8
   string s = Process.popen(cmdline*" ");
   if (s=="")
      die("\n", cmdline*" ");
   return s;
#else
   mapping r;
   mixed e = catch { r = Process.run( ({@cmdline}) ); };
   if (e || r["exitcode"])
      die("", e?e:r["stderr"]);
   return r["stdout"];
#endif
}

static mapping commits = ([]);

array parsecommits(string ... delim) {
   array res = ({});
   string id;
   array lines = run("git", "rev-list", "--format=raw",  "--ancestry-path",
                                        "--topo-order", @delim)/"\n";
   mapping branchkids = ([]);
   foreach (lines, string line) {
      array words = line/" ";
      string h = words[0];
      if (h=="commit") {
         id = words[1];
	 commits[id] = ([]);
	 res += ({id});
	 if (mapping bs = m_delete(branchkids, id))
	    commits[id]["Branch"] += bs;
	 if (mapping bs = livebranches[id])
	    commits[id]["Branch"] += bs;
      } else if (h=="") {
         if (commits[id])
            commits[id][""] += ({line});
      }
      else {
         if (h=="parent" && !commits[id]["parent"] && commits[id]["Branch"]) {
            if (branchkids[words[1]])
               branchkids[words[1]] += commits[id]["Branch"];
	    else
               branchkids[words[1]] = commits[id]["Branch"];
         }
         commits[id][h] += words[1..];
      }
   }
   return res;
}

static mapping desc = ([]);

static mapping livebranches = ([]); // id : array(name)
static mapping branchnames = ([]);  // name : void

int main(int argc, array argv) {
   argv[1] = (run("git", "rev-parse", argv[1])/"\n")[0];
   if (argc==2)
      argv += ({"master"});
   for (int i=2; i<sizeof(argv); i++) {
      string ref = argv[i];
      string refid = (run("git", "rev-parse", argv[i])/"\n")[0];
      livebranches[refid] += ([ ref : refid ]);
      branchnames[ref] = refid;
      argv[i] = refid;
   }
   array commit_list = parsecommits("^"+argv[1], @argv[2..]);
   commit_list = reverse(commit_list);
   desc[argv[1]] = 1;
   foreach (commit_list, string id) {
      if (commits[id]["parent"]) {
         foreach (commits[id]["parent"], string parent)
            if (desc[parent])
        	desc[id] = 1;
	 if (sizeof(commits[id]["parent"])>1)
            if (!desc[commits[id]["parent"][0]]) {
	       mapping reached = ([]);
	       if (commits[id]["Branch"])
	          reached = commits[id]["Branch"]&branchnames;
	       int comtime = (int)commits[id]["committer"][-2];
               write("%.12s %-56.56s %.12s\n", id, 
	              squeeze_subject(commits[id][""][1]),
		      cal->Second(comtime)->format_time_xshort() );
               if (sizeof(reached)>0) {
	          branchnames -= reached;
                  write("# Merged into %s\n", 
		          String.implode_nicely(indices(reached)) );
		  if (sizeof(branchnames)==0)
		     exit(0);
	       }
	    }
      }
      m_delete(commits, id);
   }
   write("# Not reachable from %s\n",  String.implode_nicely(indices(branchnames)) );
}

string squeeze_subject(string subject) {

   subject = String.trim_all_whites(subject);
   subject = String.expand_tabs(subject);
   foreach (sub_from_to, mapping m)
      subject = replace(subject, m);
   return subject;
}

static array(mapping) sub_from_to =
({
   ([ 
      "Merge branch " : "Merge ",
      "Merge remote branch " : "Merge ",
      "Merge branches " : "MM:",
   ]),
   ([ 
      "Merge " : "M: ",
      "' of git:": "'@git:",
      "' into ": "' => ",
   ]),
   ([ 
       "git://git.kernel.org/pub/scm/linux/kernel/git/" : "$KO/",
       "commit '" : "C'"
   ]),
});

static object cal = Calendar.ISO.set_timezone(Calendar.Timezone.UTC);

---------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-23 21:32                                     ` Artur Skawina
@ 2010-09-24  1:33                                       ` Artur Skawina
  2010-09-24 20:57                                       ` Seth Robertson
  1 sibling, 0 replies; 33+ messages in thread
From: Artur Skawina @ 2010-09-24  1:33 UTC (permalink / raw)
  To: git

> There's still a bug in there somewhere; 

JIC someone actually wants to use that script -- you'll need this:

--- git-show-merge-path	2010-09-23 20:13:59.000000000 +0000
+++ git-show-merge-path	2010-09-24 01:09:10.000000000 +0000
@@ -90,21 +89,21 @@
         	desc[id] = 1;
 	 if (sizeof(commits[id]["parent"])>1)
             if (!desc[commits[id]["parent"][0]]) {
-	       mapping reached = ([]);
-	       if (commits[id]["Branch"])
-	          reached = commits[id]["Branch"]&branchnames;
 	       int comtime = (int)commits[id]["committer"][-2];
                write("%.12s %-56.56s %.12s\n", id, 
 	              squeeze_subject(commits[id][""][1]),
 		      cal->Second(comtime)->format_time_xshort() );
-               if (sizeof(reached)>0) {
-	          branchnames -= reached;
-                  write("# Merged into %s\n", 
-		          String.implode_nicely(indices(reached)) );
-		  if (sizeof(branchnames)==0)
-		     exit(0);
-	       }
 	    }
+	 if (mapping reached = commits[id]["Branch"]) {
+	    reached = reached&branchnames;
+            if (sizeof(reached)>0) {
+               branchnames -= reached;
+               write("# Merged into %s\n",
+		       String.implode_nicely(indices(reached)) );
+	       if (sizeof(branchnames)==0)
+		  exit(0);
+	    }
+	 }
       }
       m_delete(commits, id);
    }

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made
  2010-09-18  9:19 Find out on which branch a commit was originally made Stefan Haller
  2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
@ 2010-09-24 18:26 ` Bryan Drewery
  1 sibling, 0 replies; 33+ messages in thread
From: Bryan Drewery @ 2010-09-24 18:26 UTC (permalink / raw)
  To: Stefan Haller; +Cc: git

  On 9/18/2010 4:19 AM, Stefan Haller wrote:
> I'm trying to pursuade my co-workers to switch from Subversion to Git;
> some of them prefer Mercurial.
>
> One concern that they are raising is that in Git there doesn't seem to
> be an easy way to find out on which branch a given commit was originally
> made, after the branch is merged back and deleted. They consider this a
> show-stopper.  In Mercurial, branch information is meta data attached to
> each commit, so you can easily get this information even after a branch
> is closed.
>
Use an issue tracker? Associate the commits with ticket numbers in the 
commit msg.

git commit -m "Blah Blah Blah (refs #someticket)"

Bryan Drewery

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch)
  2010-09-23 21:32                                     ` Artur Skawina
  2010-09-24  1:33                                       ` Artur Skawina
@ 2010-09-24 20:57                                       ` Seth Robertson
  1 sibling, 0 replies; 33+ messages in thread
From: Seth Robertson @ 2010-09-24 20:57 UTC (permalink / raw)
  To: Artur Skawina
  Cc: Ævar Arnfjörð Bjarmason, Stephen Bash, Stefan Haller, git


In message <4C9BC757.3050803@gmail.com>, Artur Skawina writes:

    $ time git-show-merge-path 86ab04c8c1df51df master release
    b1bc81a0ef86 M: 'master'@$KO/linville/wireless-next-2.6        090607 11:24
    36432dae73cf M: 'master'@$KO/davem/net-next-2.6                090611 14:00
    2ed0e21b30b5 M: $KO/davem/net-next-2.6                         090615 16:40
    # Merged into release and master
    0m3.056s user   0m0.207s system   0m3.154s elapsed   103.46% CPU

    Script below; w/ one or two args works like the previous
    git-find-branch-for, except it's ~two times faster for expensive
    queries and does that silly five old branch request in <13s, for
    *all* 150 heads

Thanks to your suggestion about using git rev-list with more than two
references I was able to massively increase the performance of my
script, from 26 minutes to 26 seconds, for the linux kernel search
test.

I have updated http://github.com/SethRobertson/git-what-branch to
release v0.2.1 with the performance boost and some display enhancements.

--------------------------------------------------
time git-what-branch --reference master 86ab04c8c1df51df
86ab04c8c1df51df used the following minimal temporal path:
  merged to v2.6.30-rc6-1103-gb1bc81a @Sun Jun  7 07:24:21 2009
  merged to v2.6.30-5398-g2ed0e21     @Mon Jun 15 12:40:05 2009
  v2.6.30-5398-g2ed0e21 is on master
5.97user 0.45system 0:06.08elapsed
--------------------------------------------------

    Still no ff-detection, mostly due to lack of (real) test case.

Here are some fake test cases.  The question is which branch do tags
masterE and newbrBB appear on.

# Demonstrates picking wrong branch for "master"
MERGE="git merge"
mkdir foo; cd foo; git init; echo A > A; git add A; git commit -a -m "initial"
echo B >> A; git commit -a -m "B"; echo C >> A; git commit -a -m "C"
git branch newbr; echo AB > B; git add B; git commit -a -m "newbr"
git checkout master; echo D >> A; git commit -a -m "D"; git tag masterD;
git checkout newbr; $MERGE master; echo BB >> B; git commit -a -m "BB"; git tag newbrBB
git checkout master; echo E >> A; git commit -a -m "E"; git tag masterE;
git checkout newbr; $MERGE master; echo CB >> B; git commit -a -m "CB"
git checkout master; echo F >> A; git commit -a -m "F"
git checkout newbr; $MERGE master; echo DB >> B; git commit -a -m "DB"
git checkout master; $MERGE newbr; echo G >> A; git commit -a -m "G"
echo H >> A; git commit -a -m "H"; echo J >> A; git commit -a -m "J"; git tag masterJ
git checkout newbr; $MERGE master; echo eB >> B; git commit -a -m "EB"; git tag newbrEB
git checkout master; echo K >> A; git commit -a -m "K"; $MERGE newbr
unset MERGE

# Demonstrates picking the wrong branch for "newbr"
MERGE="git merge"
mkdir foo; cd foo; git init; echo A > A; git add A; git commit -a -m "initial"
echo B >> A; git commit -a -m "B"; echo C >> A; git commit -a -m "C"
git branch newbr; echo AB > B; git add B; git commit -a -m "newbr"
git checkout master; echo D >> A; git commit -a -m "D"; git tag masterD;
git checkout newbr; $MERGE master; echo BB >> B; git commit -a -m "BB"; git tag newbrBB
git checkout master; echo E >> A; git commit -a -m "E"; git tag masterE;
git checkout newbr; $MERGE master; echo CB >> B; git commit -a -m "CB"
git checkout master; echo F >> A; git commit -a -m "F"
git checkout newbr; echo DB >> B; git commit -a -m "DB"
git checkout master; $MERGE newbr; echo G >> A; git commit -a -m "G"
echo H >> A; git commit -a -m "H"; echo J >> A; git commit -a -m "J"; git tag masterJ
git checkout newbr; $MERGE master; echo eB >> B; git commit -a -m "EB"; git tag newbrEB
git checkout master; echo K >> A; git commit -a -m "K"; $MERGE newbr
unset MERGE


					-Seth Robertson

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2010-09-24 20:57 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-18  9:19 Find out on which branch a commit was originally made Stefan Haller
2010-09-18  9:58 ` Ævar Arnfjörð Bjarmason
2010-09-18 10:02   ` Ævar Arnfjörð Bjarmason
2010-09-18 11:28   ` Tor Arntsen
2010-09-18 15:26   ` Stefan Haller
2010-09-18 16:41     ` Artur Skawina
2010-09-19  9:45       ` Stefan Haller
2010-09-19 12:54         ` Clemens Buchacher
2010-09-19 14:03         ` Artur Skawina
2010-09-19 14:08         ` Stefan Haller
2010-09-19 16:38           ` Artur Skawina
2010-09-19 18:30     ` Robin Rosenberg
2010-09-19 22:03       ` Seth Robertson
2010-09-19 23:12         ` Artur Skawina
2010-09-19 23:54           ` Seth Robertson
2010-09-20  1:31             ` Artur Skawina
2010-09-20  5:47               ` Seth Robertson
2010-09-20  8:12                 ` Stefan Haller
2010-09-20 10:58                   ` Artur Skawina
2010-09-20 15:49                     ` Artur Skawina
2010-09-21  0:15                       ` Seth Robertson
2010-09-21  2:12                         ` Artur Skawina
2010-09-22 16:35                           ` ANNOUNCE git-what-branch (was Re: Find out on which branch a commit was originally made) Seth Robertson
2010-09-22 20:27                             ` Artur Skawina
2010-09-22 23:26                               ` Find out on which branch a commit was originally made) (was ANNOUNCE git-what-branch) Seth Robertson
2010-09-23 13:14                                 ` Stephen Bash
2010-09-23 13:26                                   ` Ævar Arnfjörð Bjarmason
2010-09-23 21:32                                     ` Artur Skawina
2010-09-24  1:33                                       ` Artur Skawina
2010-09-24 20:57                                       ` Seth Robertson
2010-09-23 14:27                                   ` Seth Robertson
2010-09-20 18:20                     ` Find out on which branch a commit was originally made Stefan Haller
2010-09-24 18:26 ` Bryan Drewery

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.