{"thread":{"id":"63138","subject":"path-restricted log vs. subtree merges","startedAt":"2025-03-15T14:45:03Z","lastAt":"2025-03-17T17:43:51Z","messageCount":4,"participants":["Oswald Buddenhagen","Johannes Schindelin","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"514353","messageId":"Z9WSbUQw4VBQiOqi@ugly","threadId":"63138","inReplyTo":null,"subject":"path-restricted log vs. subtree merges","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2025-03-15T14:45:01Z","receivedAt":"2025-03-15T14:45:03Z","isPatch":false,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"in my quest to prepare for hacking git-gui, i ran\n\n   cd .../git/git-gui\n   git log .\n\nthe result is ... unhelpful. apart from a few commits that were done\ndirectly in the git repo, there are only merges. notably, there is no\ntrace of the commits that are being merged (and the way gitk presents\nthis partial log is even more unhelpful).\n\ni'm speculating that this is the result of git log not handling the\nsubtree merges in any way, with somewhat predictable consequences.\n\ni suppose there is overlap with the fact that --follow works only for a\nsingle file, which is also unfortunate. (a recent test case in the repo\nwould be templates/hooks.)\n"},{"id":"514397","messageId":"2d53bebd-e85e-7414-c7ba-bd1f31810cea@gmx.de","threadId":"63138","inReplyTo":"Z9WSbUQw4VBQiOqi@ugly","subject":"Re: path-restricted log vs. subtree merges","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2025-03-16T16:32:04Z","receivedAt":"2025-03-16T16:32:06Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Oswald,\n\nOn Sat, 15 Mar 2025, Oswald Buddenhagen wrote:\n\n> in my quest to prepare for hacking git-gui, i ran\n>\n>   cd .../git/git-gui\n>   git log .\n>\n> the result is ... unhelpful. apart from a few commits that were done\n> directly in the git repo, there are only merges. notably, there is no\n> trace of the commits that are being merged (and the way gitk presents\n> this partial log is even more unhelpful).\n>\n> i'm speculating that this is the result of git log not handling the\n> subtree merges in any way, with somewhat predictable consequences.\n\nThat sounds highly plausible.\n\n> i suppose there is overlap with the fact that --follow works only for a\n> single file, which is also unfortunate. (a recent test case in the repo\n> would be templates/hooks.)\n\nI just ran `git log --follow --raw upstream/seen -- git-gui/` and it does\nnot error out, but as you say, it is unhelpful.\n\nIt's probably not easy to fix this.\n\nI had a quick look at the relevant function (`try_to_follow_renames()` in\n`tree-diff.c`), and my intuition told me that\n\n- `choice = q->queue[0];` would need to be replaced with a loop that adds\n  the `q->queue` elements to a `strset`,\n\n- `!strcmp(p->two->path, opt->pathspec.items[0].match)` would need to be\n  scrapped in favor of testing in a loop whether `p->two->path` is matched\n  by any of `opt->pathspec.items` (because there would now be more than\n  1),\n\n- `const char *path[2];` would need to be replaced by a `strvec`, and the\n  entire `pathspec` replacing could only be done after the `for (i = 0; i\n  < q->nr; i++)` loop completed,\n\n- The `break;` out of the loop could only be done once all of the input\n  paths were accounted for.\n\nHowever, the devil lies in more details. For example, I expected that `git\nlog --follow -- git-gui/` would error out because `--follow` requires a\nsingle file to work. This suggests to me that the logic would have to be\nmodified to expand such implicit pathspec into a full list of files.\n\nAnd I imagine that the performance of this new logic may be quite\nhorrible, what with adding a nested loop for the `pathspec` matching\ninside `try_to_follow_renames()` existing loop.\n\nOf course, the fact that Git silently accepts `--follow -- <dir>/` despite\nthe fact that it cannot handle `<dir>` renames at all is a bummer.\n\nCiao,\nJohannes\n"},{"id":"514398","messageId":"xmqqo6y0dal1.fsf@gitster.g","threadId":"63138","inReplyTo":"2d53bebd-e85e-7414-c7ba-bd1f31810cea@gmx.de","subject":"Re: path-restricted log vs. subtree merges","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-03-16T19:44:42Z","receivedAt":"2025-03-16T19:44:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> I had a quick look at the relevant function (`try_to_follow_renames()` in\n> `tree-diff.c`), and my intuition told me that\n>\n> - `choice = q->queue[0];` would need to be replaced with a loop that adds\n>   the `q->queue` elements to a `strset`,\n>\n> - `!strcmp(p->two->path, opt->pathspec.items[0].match)` would need to be\n>   scrapped in favor of testing in a loop whether `p->two->path` is matched\n>   by any of `opt->pathspec.items` (because there would now be more than\n>   1),\n\nThese are needed regardless of \"following renames of directory\".\nThe fact that there is one single path being followed globally means\nthat the current \"check-box item\" design of --follow-renames would\nnot work in a mergy history, where the path that holds the contents\nbeing followed is called differently on different branches and given\na name (either taking one of the names from these branches, or a\nnname entirely different from any of the ancestors) at the merge, or\na path is renamed differently along the forked history, eventually\ngetting merged back.  Even in a \"follow this single path\" mode, you'd\nneed the notion of \"this is the path being followed while we are on\nthis single strand of commits\" that is kept per ancestors whenever\nyou hit a merge while traversing from child to its parents.\n\nThe current \"following single path\" would need to be done correctly,\nand then \"following more than one paths from anywhere in the tree\"\nwould fall out as a natural consequence once it is done.  \"following\nrenames of a directory\" would mostly be a special case of \"following\nmore than one paths from anywhere in the tree\".\n\nThanks.\n"},{"id":"514423","messageId":"20250317174343.GA704253@coredump.intra.peff.net","threadId":"63138","inReplyTo":"Z9WSbUQw4VBQiOqi@ugly","subject":"Re: path-restricted log vs. subtree merges","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-03-17T17:43:43Z","receivedAt":"2025-03-17T17:43:51Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Mar 15, 2025 at 03:45:01PM +0100, Oswald Buddenhagen wrote:\n\n> in my quest to prepare for hacking git-gui, i ran\n> \n>   cd .../git/git-gui\n>   git log .\n> \n> the result is ... unhelpful. apart from a few commits that were done\n> directly in the git repo, there are only merges. notably, there is no\n> trace of the commits that are being merged (and the way gitk presents\n> this partial log is even more unhelpful).\n> \n> i'm speculating that this is the result of git log not handling the\n> subtree merges in any way, with somewhat predictable consequences.\n\nYes, the merged-in paths and the paths in the original commits are\ndifferent. So the merge will update path \"git-gui/git-gui.sh\", etc, but\nthe individual commits are touching \"git-gui.sh\" at the root of the tree\n(in the git-gui repository).\n\nLeaving aside for a moment how --follow and other tooling could help,\nthe workaround in this case is:\n\n  git log -- git-gui/ git-gui.sh lib/\n\nYou need to ask for the paths you care about at the root-level (since\nthat's what the individual commits from the git-gui repo will have). But\nyou also need to include git-gui/; otherwise history simplification will\nnot go down the side branches from the git-gui repo (you can also use\n--full-history, but that would include a lot of irrelevant stuff). And\nyou need to use \"--\" before the paths, since the rev/path dwim logic\nwill only treat an argument as a path if it is present in the working\ntree (which the latter two paths are not).\n\n-Peff\n"}]}