{"thread":{"id":"20911","subject":"Effectively tracing project contributions with git","startedAt":"2009-09-12T12:30:17Z","lastAt":"2009-09-13T14:30:10Z","messageCount":8,"participants":["Joseph Wakeling","Jeff King","Sverre Rabbelier","Theodore Tso"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"122944","messageId":"4AAB9459.3070809@webdrake.net","threadId":"20911","inReplyTo":null,"subject":"Effectively tracing project contributions with git","fromName":"Joseph Wakeling","fromEmail":"joseph.wakeling@webdrake.net","sentAt":"2009-09-12T12:30:17Z","receivedAt":"2009-09-12T12:30:17Z","isPatch":false,"sender":{"key":"joseph.wakeling@webdrake.net","avatar":null},"body":"Hello,\n\nI've recently begun contributing to a FOSS project that has a problem --\nalthough it has extensive git logs (some being CVS/SVN imports) dating\nback over many years, there has not been maintenance of contribution\nrecords on a file-by-file basis.\n\nI'm trying to rectify this and track down who contributed what.\nUnfortunately while I'm used to basic operations with git, I don't know\nit well enough to be confident in how to go about tracing contributions\nin this way.\n\n'git annotate' of course is a nice starting point but of limited use\nbecause every time someone tweaks a line (and there have been many such\ntweaks in the history of the project) the responsibility of the original\ncontributor is replaced by that of the tweaker.\n\nAn alternative is to use gitk to trace the history of individual files\n(or paths, as gitk has it).  The problem here is that files have been\nrenamed, content has been moved about between different files and so on.\n\nFinally, there's the option to use gitk to trace contributors (someone\nhas prepared a .mailman file with a complete list of contributors by\nname and email) and manually or otherwise tally their significant\ncontributions.  Again, I'm not sure to what extent this is made\ndifficult by copy/pasting and tweaking of file content.\n\nI'm just hoping that the git community can offer some good advice on\nthis, to what extent the process of tracing contributions can be\nautomated, and so on.  I'm not expecting anyone to provide a solution\nfor me, but suggestions and pointers in the possible right directions\nwould be much appreciated.\n\nThanks & best wishes,\n\n    -- Joe\n"},{"id":"122981","messageId":"20090912185940.GA21277@coredump.intra.peff.net","threadId":"20911","inReplyTo":"4AAB9459.3070809@webdrake.net","subject":"Re: Effectively tracing project contributions with git","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-12T18:59:40Z","receivedAt":"2009-09-12T18:59:40Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Sep 12, 2009 at 02:30:17PM +0200, Joseph Wakeling wrote:\n\n> I've recently begun contributing to a FOSS project that has a problem --\n> although it has extensive git logs (some being CVS/SVN imports) dating\n> back over many years, there has not been maintenance of contribution\n> records on a file-by-file basis.\n> \n> I'm trying to rectify this and track down who contributed what.\n> Unfortunately while I'm used to basic operations with git, I don't know\n> it well enough to be confident in how to go about tracing contributions\n> in this way.\n\nWe can probably help you with the git side of things, but defining \"who\ncontributed what\" is kind of a hairy problem. You will need to define\nexactly how you want to count contributions.\n\nFor example:\n\n> 'git annotate' of course is a nice starting point but of limited use\n> because every time someone tweaks a line (and there have been many such\n> tweaks in the history of the project) the responsibility of the original\n> contributor is replaced by that of the tweaker.\n\nBut often the tweaking of the line _does_ make it their own. One of the\nmetrics often discussed in git is \"of the surviving lines in the code,\nhow many were authored by each person\". Which really is the output of\n\"git blame\" (or annotate, which is more or less the same thing). So\npeople who contribute code that needs a lot of changes or cleanup don't\nget as much credit for that code, because their lines got tweaked later.\n\nIt's an OK metric if you assume that lines are a good atom of\ncontribution. That is, if I replace your line, then I remove everything\nof value that you added and I should get credit. That is arguably not\nthe case with something like a style cleanup. Changing:\n\n  if(i = 0; i < n; i++)\n\nto\n\n  if (i = 0; i < n; i++)\n\nto fix whitespace should probably leave authorship with the original\nline. But I don't know if you can determine programatically how\nsignificant a change was. In the case of whitespace, \"git blame\" has an\noption to ignore whitespace changes, which probably covers a large\nportion of such \"trivial change\" cases.\n\n> An alternative is to use gitk to trace the history of individual files\n> (or paths, as gitk has it).  The problem here is that files have been\n> renamed, content has been moved about between different files and so on.\n\nYou can use rename detection via --follow and simply count the lines\nchanged (and by whom) in each commit. Which differs from \"git blame\"\nstrategy by counting every change as of value, even if it is a line that\ndoesn't survive.\n\nBut no, that won't handle the movement of some chunk of content from\none file to another. Only \"git blame\" really looks at code movement on a\nsmaller-than-file level.\n\n> I'm just hoping that the git community can offer some good advice on\n> this, to what extent the process of tracing contributions can be\n> automated, and so on.  I'm not expecting anyone to provide a solution\n> for me, but suggestions and pointers in the possible right directions\n> would be much appreciated.\n\nI think it is less a git problem and more of a \"how do you want to\ndefine contribution\" problem. The above is just my thinking about it for\na few minutes. Sverre Rabelier (cc'd) did a \"git stats\" GSoC project\nlast year, but I don't think I ever looked closely at the results or\nwhat metrics he came up with. But that is probably a good direction to\nlook in.\n\n-Peff\n"},{"id":"122982","messageId":"fabb9a1e0909121203r527bc81ctd68382fc1107bf06@mail.gmail.com","threadId":"20911","inReplyTo":"20090912185940.GA21277@coredump.intra.peff.net","subject":"Re: Effectively tracing project contributions with git","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-12T19:03:35Z","receivedAt":"2009-09-12T19:03:35Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Sat, Sep 12, 2009 at 20:59, Jeff King <peff@peff.net> wrote:\n> I think it is less a git problem and more of a \"how do you want to\n> define contribution\" problem. The above is just my thinking about it for\n> a few minutes. Sverre Rabelier (cc'd) did a \"git stats\" GSoC project\n> last year, but I don't think I ever looked closely at the results or\n> what metrics he came up with. But that is probably a good direction to\n> look in.\n\nGit stats can aggregate diffs, so it can show you \"this author made\nchanges to this many lines to this file in total\", but it doesn't work\nacross renames. It also has an option to aggregate that to a total per\nproject number, but I'm not sure how useful that is to your case, as\nyou seem to be interested in a per-file/line basis? I agree with Jeff\nthat you'll need to define more precisely what it is you want to know\n:).\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"123011","messageId":"4AAC36D5.1040901@webdrake.net","threadId":"20911","inReplyTo":"20090912185940.GA21277@coredump.intra.peff.net","subject":"Re: Effectively tracing project contributions with git","fromName":"Joseph Wakeling","fromEmail":"joseph.wakeling@webdrake.net","sentAt":"2009-09-13T00:03:33Z","receivedAt":"2009-09-13T00:03:33Z","isPatch":false,"sender":{"key":"joseph.wakeling@webdrake.net","avatar":null},"body":"Jeff King wrote:\n> We can probably help you with the git side of things, but defining \"who\n> contributed what\" is kind of a hairy problem. You will need to define\n> exactly how you want to count contributions.\n\nYes, that's pretty much what I'm looking for.  My thoughts on\ncontribution run along much the same lines as yours -- there's a need to\ndistinguish between meaningful additions and mere tweaks.\n\nMy general rule is that stuff like whitespace changes, changing the name\nof variables, typo corrections etc. is not a meaningful contribution\nalthough if someone had really done a lot of it I might see things\ndifferently.  Substantial additions -- extending the code, comments or\ndocumentation -- are what I'm after.  Ultimately this has to be decided\nby me actually looking at things rather than metrics.\n\nWhat I'm doing right now is to run a git shortlog on a file to get a\nrough idea of the contributors and who are likely to be the main\nauthors, then using gitk to browse the commits for that file.  It's\ntime-consuming but works -- once I've identified at least one major\ncommit from someone I can ignore everything else by them and concentrate\non the remaining contributors.\n\nWhat would help is some way to speed up the process of getting someone's\ncommits: 'give me all the diffs for file X by author Y'.  I'm not too\ngood at shell scripting so grep-y things don't spring easily to mind.\n\nAn alternative useful tool would be 'give me all the commits to this\nfile that change more than N lines'.\n\nWith those two -- particularly the first -- I think I'd be able to get a\nfair way.  It won't work for the files where there has been a lot of\nmoving of content or renames, but that's mostly in the docs -- the code,\nwhich is the really important thing, doesn't seem so bad (so far).\n\nThanks very much for the advice and careful thoughts,\n\nBest wishes,\n\n    -- Joe\n"},{"id":"123014","messageId":"4AAC3889.6030908@webdrake.net","threadId":"20911","inReplyTo":"fabb9a1e0909121203r527bc81ctd68382fc1107bf06@mail.gmail.com","subject":"Re: Effectively tracing project contributions with git","fromName":"Joseph Wakeling","fromEmail":"joseph.wakeling@webdrake.net","sentAt":"2009-09-13T00:10:49Z","receivedAt":"2009-09-13T00:10:49Z","isPatch":false,"sender":{"key":"joseph.wakeling@webdrake.net","avatar":null},"body":"Sverre Rabbelier wrote:\n> Git stats can aggregate diffs, so it can show you \"this author made\n> changes to this many lines to this file in total\", but it doesn't work\n> across renames. It also has an option to aggregate that to a total per\n> project number, but I'm not sure how useful that is to your case, as\n> you seem to be interested in a per-file/line basis? I agree with Jeff\n> that you'll need to define more precisely what it is you want to know\n> :).\n\nThat would certainly be a very useful function -- it wouldn't solve my\nproblem for me but would make it easier to identify core authors.  After\nall, 'number of commits' doesn't necessarily correspond to meaningful\ncontribution -- many of them could be editorial -- but number of lines\n(or the ratio of lines to commits) could be a much better indicator.\n\nI don't see any solution that doesn't see me browsing diffs -- there's\nno metric that will solve the problem -- but if your stats work could\nhelp me get an output of the form 'here are all the diffs on file X by\ncontributor Y in order of size, largest first' then I think it would\nhelp a LOT.\n\nIs there a website where I can read more about your stats/metrics work?\n Beyond the applications to the present problem I have some other\nreasons to be very interested in what can be done with git history stats.\n\nThanks & best wishes,\n\n    -- Joe\n"},{"id":"123018","messageId":"20090913022843.GB26588@mit.edu","threadId":"20911","inReplyTo":"4AAC3889.6030908@webdrake.net","subject":"Re: Effectively tracing project contributions with git","fromName":"Theodore Tso","fromEmail":"tytso@mit.edu","sentAt":"2009-09-13T02:28:43Z","receivedAt":"2009-09-13T02:28:43Z","isPatch":false,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"On Sun, Sep 13, 2009 at 02:10:49AM +0200, Joseph Wakeling wrote:\n> \n> I don't see any solution that doesn't see me browsing diffs -- there's\n> no metric that will solve the problem -- but if your stats work could\n> help me get an output of the form 'here are all the diffs on file X by\n> contributor Y in order of size, largest first' then I think it would\n> help a LOT.\n\nThis will display all of the diffs on file (pathname) XXX by contributor YYY:\n\n\tgit log -p --author=YYY XXX \n\nYou might also find the diffstats useful:\n\n\tgit log --stat --author=YYY XXX\n\nOr if you want *only* the diffstats for the file in question, you might try:\n\n\tgit log --stat --pretty=format: --author=YYY XXX | grep XXX\n\nSo the bottom line is git will allow you to extract quite a lot of\ninformation.  You might need to do some perl- or shell- or python-\nscripting to analyze or format the information, but the harder\nquestion is determining exactly what question you want to ask.\n\nEliminating whitespace changes isn't hard (add the -b flag).  If you\nwant to eliminate variable renaming, that's harder since that requires\nactually parsing the patch.  There are programs that will do that\n(normally used by University professors to catch students cheating at\nProgramming 101 courses :-), but you'd need to do some shell (or perl\nor python) scripting to splice them into the git invocations to\nextract out the information.\n\nIs there a particular reason why this is important to you?  Is it for\ncuriosity reasons; are you trying to build a case that you've\ncontacted all of the significant contributors for the purposes of\nchanging the license used on a file?  If it's the latter, what I'd\nprobably do is just simply collect everyone who has ever changed a\nfile (git log --format=\"%aN <%aE>\" pathname/to/a/file | sort -u) and\ntry to get as many people as possible to agree to the license change.\nFor the ones who have _not_ agreed, or which you can not contact, you\ncan go back and just analyze their changes (git log --author=YYY) to\ndecide whether or not they are significant, and whether you need to\ntry extract hard to contact them, or in the worst case, find someone\nto rewrite the parts of the file which they had modified in the past.\n\nOr maybe you have some other reason for gathering said information.\nDepending on what the high-level thing it is that you are trying to\ndo, there may be an easier or more elegant way to get the information\nyou are requesting.\n\n\t\t\t\t\t\t- Ted\n"},{"id":"123040","messageId":"20090913092429.GA14438@coredump.intra.peff.net","threadId":"20911","inReplyTo":"20090913022843.GB26588@mit.edu","subject":"Re: Effectively tracing project contributions with git","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-13T09:24:30Z","receivedAt":"2009-09-13T09:24:30Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Sep 12, 2009 at 10:28:43PM -0400, Theodore Tso wrote:\n\n> > I don't see any solution that doesn't see me browsing diffs -- there's\n> > no metric that will solve the problem -- but if your stats work could\n> > help me get an output of the form 'here are all the diffs on file X by\n> > contributor Y in order of size, largest first' then I think it would\n> > help a LOT.\n> \n> This will display all of the diffs on file (pathname) XXX by contributor YYY:\n> \n> \tgit log -p --author=YYY XXX \n> \n> You might also find the diffstats useful:\n> \n> \tgit log --stat --author=YYY XXX\n> \n> Or if you want *only* the diffstats for the file in question, you might try:\n> \n> \tgit log --stat --pretty=format: --author=YYY XXX | grep XXX\n\nThere is also the \"--numstat\" format which is a bit easier for parsing.\nI think the \"all diffs on file $X by contributor $Y, ordered by size\"\nwould look like:\n\n  git log -z --pretty=tformat:%H --numstat --author=$Y $X |\n  perl -0ne '\n    my ($commit) = /^([0-9a-f]{40})$/m;\n    my ($lines_added) = /^(\\d+)\\s/m;\n    print \"$lines_added $commit\\n\";\n  ' |\n  sort -rn |\n  cut -d ' ' -f2 |\n  xargs -n 1 git show\n\n-Peff\n"},{"id":"123059","messageId":"4AAD01F2.5010803@webdrake.net","threadId":"20911","inReplyTo":"20090913022843.GB26588@mit.edu","subject":"Re: Effectively tracing project contributions with git","fromName":"Joseph Wakeling","fromEmail":"joseph.wakeling@webdrake.net","sentAt":"2009-09-13T14:30:10Z","receivedAt":"2009-09-13T14:30:10Z","isPatch":false,"sender":{"key":"joseph.wakeling@webdrake.net","avatar":null},"body":"Theodore Tso wrote:\n> This will display all of the diffs on file (pathname) XXX by contributor YYY:\n> \n> \tgit log -p --author=YYY XXX \n> \n> You might also find the diffstats useful:\n> \n> \tgit log --stat --author=YYY XXX\n> \n> Or if you want *only* the diffstats for the file in question, you might try:\n> \n> \tgit log --stat --pretty=format: --author=YYY XXX | grep XXX\n\nThat's absolutely brilliant -- using these commands makes my task much\neasier.\n\nAs for reasons -- there are several.  For the FOSS project, here is a\npotential relicensing issue (guarding against future problems rather\nthan addressing present ones) and indeed I'm going about it the way you\nsuggest -- getting consent from as many contributors as possible.\nDespite that, it seems useful to have up-to-date file-by-file credits\nand copyright notices.\n\nPersonally, there's also a degree of curiosity and wanting to learn some\nof the more complex and advanced possibilities of git -- and also\nbasically wanting to see to what extent this task is possible.  How\nfine-grained a degree of credit/blame can I extract for a given piece of\ncode?  And how far back in history? etc.\n\nFinally, there's an aspect which has nothing to do with code but could\nstill be very interesting for some people in the git community.  I've\nlong been fascinated by DVCS as a collaborative tool and over the last\nyear have been part of the Liquid Publications project:\nhttp://project.liquidpub.org/\n\n... that is trying to develop new models for scientific collaboration\nand publishing/sharing of results and ideas.  One of my interests is to\nsee whether DVCS can be harnessed to enable better and more open\ncollaboration and micro-credit for scientific contributions.\n\nWe've already set up a project on Launchpad to try to turn one of our\nproject reports into a review paper via open collaboration:\nhttps://code.launchpad.net/~webdrake/liquidpub/peer-review\n\n... and I'll shortly be setting up a GitHub branch for another,\nfrom-scratch article directly on DVCS and their potential applications\n(the use of different VCS is deliberate: one thing I'll be doing is\ntesting different VCS and their different features).  This is something\nI'd very much like to have git (and bzr, and hg) community members\ninvolved in.\n\nI was going to write to the git community about this at a later date\nonce I'd got more stuff prepared, but since the present discussion could\ngenerate useful material for that it seems only fair to be open.\n\nThe FOSS project stuff has nothing to do with that, but I certainly see\nit as a good experience to feed the LiquidPub research.\n\nThanks for the useful advice and best wishes,\n\n    -- Joe\n"}]}