lazygit icon indicating copy to clipboard operation
lazygit copied to clipboard

File history filter doesn’t show commit details before the file was renamed

Open lilei1508 opened this issue 7 months ago • 6 comments

Describe the bug When using the file history filter feature (lazygit -f filename), commits that occurred before the file was renamed are not displayed in the patch panel. This makes it impossible to view the complete history of a file that has been renamed at some point.

To Reproduce Steps to reproduce the behavior:

  1. Create a new file foo.txt and commit it
  2. Rename foo.txt to bar.txt and commit the rename
  3. Run lazygit -f bar.txt to filter commit history by this file
  4. Navigate to the first commit in the list (the one where foo.txt was created)
  5. The Patch panel shows blank content instead of displaying the initial file creation

Screenshots lazygit log Image Image

lazygit -f bar.txt Image

Version info: commit=5f809809dda06c98e51743ac8c19af6a26a5984b, build date=2025-04-14T08:30:35Z, build source=binaryRelease, version=0.49.0, os=darwin, arch=arm64, git version=2.32.1 (Apple Git-133)

lilei1508 avatar Apr 25 '25 03:04 lilei1508

It's easy to explain why this happens: when obtaining the list of commits to display, we call git log --follow -- <filepath>. The --follow takes care of showing all commits that affect the file, even across renames. However, to then show the diff of each commit as you select it, we use git show <sha> -- <filepath>, and this of course doesn't work for the commits where the file had a different name.

I'm not really sure what we can do about it. We'd have to call something like git log --follow --name-status -- <filepath> to learn about renames, and track them ourselves, and store that information in our commits objects somehow. This seems like a lot of work, and also it will probably make it slower; and I already find filtering by path annoyingly slow in large repos.

As a better-than-nothing workaround, I wonder if we should provide a way to toggle to a full diff instead of the filtered diff by file path. Actually I had that wish a few times in the past, independent of the rename problem; sometimes it's useful to see the diffs in context. Not always though, so it needs to be optional.

If we want to add that, there are a few questions to answer:

  • how do you toggle? I wouldn't want to make it its own keybinding, because the list of local keybindings in the commits panel is so long already, and keybindings are scarce. We could add a menu entry to the ctrl-s filter menu, and maybe it would only appear when you are in filter-by-path mode. But that requires two keystrokes to toggle it, and maybe it's not discoverable enough (many people probably never look at the menu when they are in a filter mode, and just use esc to end it).
  • how persistent is it? I suppose we should save the setting in state.yml, like we do for "ignore whitespace". Another option would be to add a user config for the initial value, and then allow toggling at runtime from there, but don't persist it, like we do for the "show/hide command log" setting.
  • do we need to display the state somewhere, like we do for "ignore whitespace", or is it clear enough from the diff which mode you're in?

Any opinions about these @jesseduffield?

stefanhaller avatar May 25 '25 12:05 stefanhaller

Here's a quick draft PR implementing this: #4594.

stefanhaller avatar May 25 '25 13:05 stefanhaller

Haven't had enough time to digest the questions you've posed @stefanhaller : but I wonder if we could run some cheap command to list the files of the commit, see if the filtered file is included, and if not, display the entire commit unfiltered? That spares us from having to introduce a new option at all

jesseduffield avatar May 29 '25 13:05 jesseduffield

but I wonder if we could run some cheap command to list the files of the commit, see if the filtered file is included, and if not, display the entire commit unfiltered? That spares us from having to introduce a new option at all

That's a good idea. Seems that git show --name-only <sha> takes somewhere between 5 and 15ms on my machine, depending on commit, so this looks feasible. I can give it shot.

However, my point was that an option to switch to the full diff would be useful on its own, independent of the rename problem. In my opinion, seeing the filtered diff is useful as long as you go through the list of commits to find the one that you are interested in, but once I found it, I wish I could switch to a full diff to see more information. On the other hand, in most cases this only concerns the very last commit that I ended up looking at, so maybe it would be good enough to keep that commit selected upon exiting filter mode, which we currently don't do.

stefanhaller avatar May 29 '25 15:05 stefanhaller

so maybe it would be good enough to keep that commit selected upon exiting filter mode, which we currently don't do.

Oh wait, we do this already; however, in many cases that commit is not included in the first 300 after exiting filter mode and can't be selected. Bummer.

stefanhaller avatar May 29 '25 17:05 stefanhaller

I spoke too soon (not the first time this happens 😄) when I said above that a real fix isn't possible. I played a bit with using --name-status to track the rename information, and first experiments show very promising results. This is totally feasible. I still need some more time to work out some edge cases, e.g. showing a range diff across a rename, but we can totally do this.

I would still like to have an option to switch to a full diff on demand, but this is becoming an unrelated feature request then.

stefanhaller avatar May 30 '25 11:05 stefanhaller

@ahh1508 Here's a PR that will fix this, in case you want to test it: #4750.

However, my point was that an option to switch to the full diff would be useful on its own, independent of the rename problem. In my opinion, seeing the filtered diff is useful as long as you go through the list of commits to find the one that you are interested in, but once I found it, I wish I could switch to a full diff to see more information.

I meanwhile realized that you can hit enter on a commit, and this will show all changed files of the commit, not just the filtered ones. This is good enough as a workaround for me.

stefanhaller avatar Jul 17 '25 19:07 stefanhaller

@stefanhaller turns out I worked on the same issue with https://github.com/jesseduffield/lazygit/pull/4773 let me know if the approach is of interest

parisni avatar Jul 26 '25 20:07 parisni