git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Artur Skawina <art.08.09@gmail.com>
To: Stefan Haller <lists@haller-berlin.de>
Cc: Seth Robertson <in-gitvger@baka.org>, git@vger.kernel.org
Subject: Re: Find out on which branch a commit was originally made
Date: Mon, 20 Sep 2010 17:49:55 +0200	[thread overview]
Message-ID: <4C9782A3.5010005@gmail.com> (raw)
In-Reply-To: <4C973E5B.4090201@gmail.com>

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 );
	 }
   }
}
------------------------------------------------------------------------------

  reply	other threads:[~2010-09-20 15:50 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C9782A3.5010005@gmail.com \
    --to=art.08.09@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=in-gitvger@baka.org \
    --cc=lists@haller-berlin.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).