{"thread":{"id":"16067","subject":"alternate log --follow idea","startedAt":"2008-10-28T06:44:28Z","lastAt":"2008-10-28T06:44:28Z","messageCount":1,"participants":["Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"94094","messageId":"20081028064425.GA26450@sigill.intra.peff.net","threadId":"16067","inReplyTo":null,"subject":"alternate log --follow idea","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-10-28T06:44:28Z","receivedAt":"2008-10-28T06:44:28Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"At the GitTogether this morning, I mentioned an alternate idea for\nlooking at the history of a file that moved. Currently we have:\n\n 1. git log <path>\n\n    Show the commits, in reverse chronological order, that touched any\n    content that at the time of touching resided at <path>.\n\n 2. git log --follow <path>\n\n    Show the commits, in reverse chronological order, for the content\n    currently in <path>, where we find movement of content from one path\n    to another by checking single commits, and say either \"all of this\n    content moved from one path to another\" or not.\n\n 3. git blame <path>\n\n    Show the current content of <path>, but with each line of content\n    showing the commit that introduced it.\n\nIn a repository with moving files, '1' is often insufficient or\nannoying, since you get to the \"root\" of the file and discover that it\nreally came from somewhere else. In other words, you never really cared\nabout that path at all, but rather about the _content_ in it.\n\nSo you try '2', but that has its own drawbacks.  It only works on one\nfile at a time, and it doesn't work on many cases, including \"git log\n--follow git-gui/git-gui.sh\".\n\nSo you move to '3', which sort of works. It shows you the commits that\nintroduced the current content, but not in the log format. That is, if\nyou don't care about \"which commit introduced this particular line\" but\nrather \"what are the commits that created this content\", it is not very\nuseful. You see the same commits repeated (since they often change many\nlines), the commits are shown in file order rather than reverse\nchronological order, and you don't get the usual nicely formatted log.\n\nSo the new idea is very simple: look at the current content, get the\nlist of all commits which were involved in creating that content, and\nthen display them as a flattened history in the usual git-log way.\n\nThe script below implements a very naive version:\n\n-- >8 --\n#!/bin/sh\n\ndashed() {\n\tfor i in \"$@\"; do\n\t\tcase \"$i\" in\n\t\t-*) echo $i ;;\n\t\tesac\n\tdone\n}\n\nnondashed() {\n\tfor i in \"$@\"; do\n\t\tcase \"$i\" in\n\t\t-*) ;;\n\t\t*) echo $i ;;\n\t\tesac\n\tdone\n}\n\n# hope we don't have spaces in our arguments\ngit ls-files `nondashed \"$@\"` |\nwhile read file; do\n\tgit blame --porcelain \"$file\" |\n\tegrep '^[0-9a-f]{40}' |\n\tcut -d' ' -f1\ndone |\nsort -u |\nxargs git log --no-walk `dashed \"$@\"`\n-- >8 --\n\nYou can try:\n\n  sh blame-log.sh git-gui/git-gui.sh\n\nwhich should Just Work. Because it expands its arguments via ls-files,\nyou can also track the content of a whole directory:\n\n  sh blame-log.sh -p contrib/examples\n\nwhich finds all of the commits that touched those files, even when they\nwere not yet in contrib (in fact, it even traces some of the lines back\nto git-tag-script!).\n\nOf course it has its downsides (aside from this horrific\nimplementation). For one thing, it's _way_ slower than a regular log,\nespecially on a large chunk of content.  Some of that is in the\nimplementation, but mostly it is that blame takes a lot of computation.\nWe might be able to make things better with a specialized blame.\n\nAnd as somebody (I think Steven) mentioned earlier, it only traces\ncontent which survived to the end. So it won't mention commits which\nwere later eradicated, which may be useful to see.\n\nAnd I'm sure there are probably other little problems, as I haven't\nthought too deeply about this. But maybe it is worth adding to the\narsenal of exploration tools.\n\n-Peff\n"}]}