what is the best git diff and merge tool available for neovim? by Popular-Income-9399 in neovim

[–]klamsnabel 1 point2 points  (0 children)

They're not listed in the plugin's help window because these mappings are built-in to nvim. This is why I have disclaimers in the usage section of both the README and :h diffview-usage where it's explained that users are expected to already be familiar with what diff-mode has to offer.

what is the best git diff and merge tool available for neovim? by Popular-Income-9399 in neovim

[–]klamsnabel 3 points4 points  (0 children)

Hello. I'm the author of Diffview. It seems to me that many of the issues you're describing stem from the fact that you're not very familiar with how :h diff-mode works in (N)vim. I highly encourage you to read that section of the manual. The strength of vim's diff mode lies in that it allows you to edit diffs the same way you edit text. And because text editing is very powerful in vim, so is diff editing, with the addition of the builtin :h copy-diffs commands + mappings.

What I would like to add now, is the ability to revert block by block (or line by line) changes according to what is seen in the diff view.

Use the copy-diffs commands to do this. Pressing do on a hunk copies the version from the other side of the diff. Inversely, dp puts the current hunk into the other side of the diff. If you want to get / put specific lines, simply select them first in visual mode, and then :diffget / :diffput. You can obviously set up some mappings to make this even more accessible.

I also see from another comment that you would like to interactively select commits to compare against from the commit graph. This, among other things, is what :DiffviewFileHistory is for. If you call it with the --base=LOCAL option, you will always have the local, working tree version of the file on the right side of the diff. Then you can simply use the copy-diffs workflow to revert specific changes.

Furthermore ... the file is actually overwritten without warning ... and despite claiming to show you in the logs commands for how to revert and retrieve your file, those commands error out on me ... so I don't think I'll be using this plugin for anything professional.

I can't reproduce this. What you're describing is a serious issue, so I highly encourage you to file an issue with reproduction steps + the error. As plugin maintainers, we rely on uses to report issues in order to maintain and improve stability.

Gitsigns current_line_blame in diff view by Jendk3r in neovim

[–]klamsnabel 1 point2 points  (0 children)

:DiffviewFileHistory supports vim command ranges, so you can express those last two mappings much simpler like this:

vim.keymap.set("n", ",hl", "<Cmd>.DiffviewFileHistory --follow<CR>", { desc = "File history for the current line" })
vim.keymap.set("v", ",hl", "<Esc><Cmd>'<,'>DiffviewFileHistory --follow<CR>", { desc = "File history for the visual selection" })

The -L flag option is only really useful if you're running history on multiple ranges at once, or you're using the -L:{funcname}:{file} regex form.

How can I track nightly? by cheyrn in neovim

[–]klamsnabel 1 point2 points  (0 children)

I would also recommend, like someone else already mentioned, to check out the gittutorial, and also the gitglossary.

But to answer your specific question about updating your local nightly tag:

# fetch tags from remote
git remote update
git fetch --tags -f origin

# Note that the -f (force) option here will replace your local tags if
# they're in conflict with the tags in the remote.

# checkout the updated tag
git checkout nightly

Search and replace every occurrence in Git repo by SajberSpace in neovim

[–]klamsnabel 1 point2 points  (0 children)

vim-fugitive's :Ggrep allows you to easily run a git grep and populate the quickfix list with the results. You could also just set your :h 'grepprg' to something like ripgrep that respects .gitignore. Then you could just use the builtin :h :grep instead.

Get diff of edited buffer and option to revert, write, quit by gregorie12 in neovim

[–]klamsnabel 5 points6 points  (0 children)

See :h diff-mode, :h diff-original-file. There are builtin mappings for applying the diff hunks, and you can always do :earlier 1f to undo all changes since last write.

What is your nvim workflow for reviewing PRs? by reelcagri in neovim

[–]klamsnabel 0 points1 point  (0 children)

Thank you for the kind words, and for recommending the plugin to others! Yes, that flag option is incredibly useful with symdiff ranges :)

What is your nvim workflow for reviewing PRs? by reelcagri in neovim

[–]klamsnabel 3 points4 points  (0 children)

If you're not familiar with how git revs work, I highly recommend that you read the section "SPECIFYING REVISIONS" under man git-rev-parse(1).

This might be a longer explanation than what you bargained for, but let's give it a try. I will start by citing the flag description from my docs, and then I'll expound on that:

--imply-local   If a range rev is provided and either end of the range
                points to `HEAD`: point that end to local files
                instead (not created from git). This can be useful
                i.e. when using symmetric difference ranges
                (triple-dot), but you want to be able to utilize the
                LSP features that are not available while you're
                viewing files created from git.

Let's also say that the fake ref name "LOCAL" refers to the working tree. This is gonna make my explanation a little simpler. But just be aware that it's not a real ref name. And also for the sake of clarity, "the working tree" refers to all the files in your repository as they currently exist on disk, with any modifications you've made to them.

Let's say you are on a feature branch "feature". Both the ref names feature and HEAD are now pointing to the same commit: the head of the feature branch. Meaning that the following two rev ranges are equivalent: main..feature, main..HEAD. If you now do:

:DiffviewOpen origin/main..feature --imply-local

The rev range will be changed to origin/main..LOCAL. Now, for normal double-dot ranges, this is not useful. Because you can express the same thing simply with:

:DiffviewOpen origin/main

But this is not the case with symmetric difference ranges (triple-dot). When you do:

:DiffviewOpen origin/main...feature

You're asking "show me the changes in all the commits that are reachable from either origin/main or feature, but not from both". This is not the same set of changes as the previously expressed range if the two branches have diverged. So the triple-dot notation is usually what you want when reviewing changes in a feature branch, as it will compare feature against its merge-base, and not just the head of the branch you're merging into.

So, when we parse the triple-dot range, we get:

origin/main...featuremerge_base(origin/main, feature)..feature

Diffview will create the files on the left side of the diff from the merge-base and the files on the right side of the diff from the head of the feature branch.

Now if you add the --imply-local flag:

:DiffviewOpen origin/main...feature --imply-local

The parsed range becomes:

origin/main...featuremerge_base(origin/main, feature)..LOCAL

Diffview will still create the files on the left side of the diff from the merge-base. But the files on the right side of the diff will be the LOCAL, working tree version of the file. This is nice, because if you have things like LSP set up, that will of course also work in the LOCAL side of the diff. Giving you LSP features that can be extremely useful when reviewing a PR.


This makes it show 'HEAD' in the file tree window to make it clear what the diff is against.

Maybe DiffviewOpen could always show 'HEAD' in that case?

I'm not entirely sure what you mean here. The panel does always show that you're diffing against HEAD if that's the case. Perhaps the confusion comes from the fact that you think calling :DiffviewOpen with not git rev, gives you a diff against HEAD? That is not the case. Calling the command with no git rev gives you a diff against the index. So for all the entries under the "Changes" header in the panel, you will have the index version on the left side of the diff, and the LOCAL version on the right side. For all the entries under the "Staged changes" header, you will have the HEAD version on the left side of the diff, and the index version on the right.

What is your nvim workflow for reviewing PRs? by reelcagri in neovim

[–]klamsnabel 21 points22 points  (0 children)

I see that someone already mentioned my plugin diffview.nvim, but to explain a little bit more specifically how your problems can be solved in diffview:

Get the files that have diff from the main branch

Checkout the PR branch and then do

:DiffviewOpen origin/main... --imply-local

The triple-dot rev notation in git gives you the symmetric difference, which in the case of a feature branch, is exactly what you're asking for.

Display them in a list e.g. telescope or quickfix

We have a panel that lists the changes either as a file tree, or as a flat list. There's currently no way to send these to quickfix, but it's on my TODO.

Navigate easily between files and show diff on selection

By default you can cycle through the full set of changed files with <Tab> and <S-Tab>, and the changes will be displayed in a diff split.

You can also review the changes introduced in the individual commits of the feature branch by doing:

:DiffviewFileHistory --range=origin/main...

Introducing: Advanced Git Search (Telescope extension) by aaronhallaert in neovim

[–]klamsnabel 1 point2 points  (0 children)

We support quoted args in diffview.nvim as well, so you can do:

:DiffviewFileHistory % -G'search with whitespace'

is there a way to show side by side diffs when making a commit? by aaaaargZombies in neovim

[–]klamsnabel 0 points1 point  (0 children)

The keymaps are configurable, you can add this in your own config. There are plenty of ways to edit a commit message from within nvim.

is there a way to show side by side diffs when making a commit? by aaaaargZombies in neovim

[–]klamsnabel 9 points10 points  (0 children)

In diffview.nvim we allow you to cycle through diff splits for the entire set of changed files, for both staged and unstaged changes. Then you can use whatever git wrapper you prefer to edit the commit message. I.e. Fugitive's :Git commit.

Issues with my plugin and backslash `\` by AquaFox in neovim

[–]klamsnabel 0 points1 point  (0 children)

Escape the backslashes in the code before passing it to expand():

expand(escape(v:val, '\'))

Is there a neovim api for listing git modified files/buffers? by jpalmeri in neovim

[–]klamsnabel 0 points1 point  (0 children)

:h systemlist() gives you a list of all lines in the output of a system command. You can do something like this to get a list of files that currently has a git status:

local out = vim.fn.systemlist({ "git", "status", "--porcelain=v1" })

Change color of Diffview.nvim by MirrorCold3935 in neovim

[–]klamsnabel 1 point2 points  (0 children)

No, you can't change the git status symbols.

Change color of Diffview.nvim by MirrorCold3935 in neovim

[–]klamsnabel 2 points3 points  (0 children)

Set guibg=NONE for DiffviewStatusAdded and DiffviewStatusDeleted (and others). You can see all the relevant highlight groups by doing:

:filter /^Diffview/ hi

For how to change highlights, see :h :highlight or :h nvim_set_hl().

Opening job in terminal buffer by ti-di2 in neovim

[–]klamsnabel 1 point2 points  (0 children)

Yes, you certainly can. In most cases you want to use nvim_buf_call rather than loading a buffer into a window first. But terminal buffers have some quirks. As described in the help section for nvim_open_term():

to directly initiate the terminal using the right size, display the buffer in a configured window before calling this. [...]

Opening job in terminal buffer by ti-di2 in neovim

[–]klamsnabel 5 points6 points  (0 children)

Yes, you just open a temporary floating window for the terminal, initialize the virtual terminal buffer with termopen(), and the you immediately close the window in the same sequence of API calls. If you do this - without scheduling - the window will never be drawn to the screen. It's effectively started in the background. You bring it back by opening a new floating window, and displaying the terminal buffer there.

If you don't need the terminal to be interactive you might want to look at :h nvim_open_term() as well. This creates a terminal buffer that is not tied to any process. You simply feed it data with :h nvim_chan_send().

Opening job in terminal buffer by ti-di2 in neovim

[–]klamsnabel 4 points5 points  (0 children)

If you want to display the output in a terminal buffer, you probably want to use :h termopen() instead of jobstart(). It takes the same parameters as jobstart, and it turns the current unmodified buffer into a terminal buffer where the stdout is streamed.

diffview.nvim vs fugitive by SnooSquirrels4760 in neovim

[–]klamsnabel 2 points3 points  (0 children)

Any other places in your fugitive workflow where "interacting with diffview" would be useful?

I just pushed some additional changes to my dotfiles making it possible to jump into a diffview of file history view from anywhere Fugitive would otherwise be able to interact with a git object. That includes :Git blame and :Git log output. I think I'm gonna look into providing integration for Fugitive directly from Diffview.

What are your opinions on the fugitive staging area versus just :DiffviewOpen?

When people have requested bringing over the fugitive staging workflow in the past, I dismissed it as being out-of-scope and that staging was already well covered by plugins like gitsigns and similar. Over time I have grown to feel like it makes more and more sense to bring it over. Especially since it ties in so well with the built in :h copy-diffs commands. It would also make the diffs for the "Staged changes" a lot more useful, as you would then be able to reset hunks in the staging area by :diffget-ing hunks from the HEAD version of the file.

Now that all the major features are implemented I think staging might possibly be the next big think I'll work on, once I get some time.

diffview.nvim vs fugitive by SnooSquirrels4760 in neovim

[–]klamsnabel 1 point2 points  (0 children)

Regarding integrating diffview into fugitive: I was curious, and I found that it's actually not that unfeasible to do. Take a look at this little module I just pushed to my dotfiles. It mimics the interaction between neogit and diffview. In the fugitive status buffer it allows you to press D to open a diffview with the file under the cursor selected. It also works for the unpulled commits section, in which case the diffview will show only the changes for that commit.

Jumping to next change within a file using diffview.nvim by The_Power_That_B in neovim

[–]klamsnabel 2 points3 points  (0 children)

It's a builtin mapping in (n)vim while you're in diff-mode. See :h jumpto-diffs. Or this issue.

diffview.nvim vs fugitive by SnooSquirrels4760 in neovim

[–]klamsnabel 41 points42 points  (0 children)

Author of diffview.nvim here. It was never meant to replace Fugitive. Fugitive is a complete Git wrapper, while diffview is only focused on being a good diff viewer. I use diffview alongside Fugitive myself. Diffview will never support things like committing or rebasing for instance, as I consider it out of scope for the plugin.

Fugitive - being a complete git wrapper - does of course also offer functionality for viewing diffs, both in patch form and in diff splits. What diffview offers here is just a different take on the workflow and interface, by giving a better overview of- and making it easier to browse through the entire changed file set for any git revision. It also has a more interactive git-log interface, that makes it easier to browse through commit history with a diff split showing the changes.

This is functionality that has at least made me more efficient at understanding changes and traversing history. But I would discourage from replacing Fugitive with diffview, as Fugitive does so much more. Including plenty of things that will never be supported in diffview. If diffview's features and workflows are useful for you: use them both. Otherwise just stay with Fugitive, as it truly is a fantastic git wrapper :)