-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Easy way to move between diffs (Unimpaired-style) #132
Comments
I've been thinking of adding a way to load the dirty files into the quickfix list. Then you'd just need some map like |
It sounds like the more general case is loading a changeset into the quickfix list. That could be the changes not in the index ( However, |
Not really. It has occurred to me that we could use the quickfix "message" field to store the filename to diff against. Then some command could retrieve that message and use it to load the diff. Question is, how do we retrieve that message? |
Well, if there's only one entry per file, we can find the only entry for the newly-activated buffer. |
I'd rather decouple and have a method for "load the original for the current quickfix entry" rather than some monster workflow map. Although it might be okay to have |
👍 How about 3 commands for loading unstaged, loading untracked, and loading both? I agree that the best approach is commands to populate the quickfix and leaving the rest to the user. I'm happy to work on this if you agree with this approach. |
As discussed on IRC, I'm still super hesitant about the original use case, but I'm on board with a much simpler |
I've been thinking about this a lot and am debating the merits of a more generic command that accepts any git command as an argument and treats the output as files for the quickfix list. The main use case I've thought of for this would be Please feel free to chime in with any thoughts on this. I've discussed it with @qstrahl and he and/or I might play around with a few possible implementations. |
For what it's worth, here's a gist with what I have in my dotfiles to do this currently: https://gist.github.com/mattboehm/9977950 . It's very similar to what tpope suggested initially: Splits into a new tab and nukes any other windows in the tab any time you go to next/prev diff. It would take a bit of work to extend this to work for #425 but not too much. In the meantime, I'll try to make a PR for this story soon. Sorry for the delayed response. |
Something I'm doing as a workaround for now: $ git checkout -b compare
$ git reset the-branch-to-compare-to
$ vim
:Gstatus
Look at all the diffs
Maybe make some changes to touch things up
:qa
$ git checkout the-original-branch
$ git commit the changes |
Prompted by an email I've started to think about this anew. My unmerged files use case has since been addressed by Between no argument, |
So as I understand it, the steps for the original use case would be:
That seems pretty reasonable to me, although I think that overloading For what it's worth, you could try to include both commit ID's into 1 fugitive url so that |
Usage described at: http://stackoverflow.com/a/36190738/895245 function! Find(regex, find, git_toplevel)
if (a:git_toplevel)
let l:toplevel = system('git rev-parse --show-toplevel')
if (v:shell_error)
echomsg 'Not in a Git repo?'
return
endif
execute 'lcd ' . l:toplevel
endif
let l:files = system(a:find . " | grep -E " . shellescape(a:regex))
if (v:shell_error)
echomsg 'No matching files.'
return
endif
tabedit
set filetype=filelist
silent file [filelist]
set buftype=nofile
put =l:files
normal ggdd
nnoremap <buffer> <Enter> <C-W>gf
execute 'autocmd BufEnter <buffer> lcd ' . getcwd()
endfunction
command! -nargs=? Find call Find('<args>', 'find . -type f', 0)
command! -nargs=? Gfind call Find('<args>', 'git ls-files', 0)
command! -nargs=? Gtfind call Find('<args>', 'git ls-files', 1) |
I did this with a little perl script and a couple mappings. Mine loads the quickfix with all of the hunks instead of each file, which was more what I wanted. If anyone is interested you can read about it here |
Wrote this small snippet to be able to diff branches, doesn't use fugitive " ----------------------------------------------------------------------------
" DiffRev
" ----------------------------------------------------------------------------
let s:git_status_dictionary = {
\ "A": "Added",
\ "B": "Broken",
\ "C": "Copied",
\ "D": "Deleted",
\ "M": "Modified",
\ "R": "Renamed",
\ "T": "Changed",
\ "U": "Unmerged",
\ "X": "Unknown"
\ }
function! s:get_diff_files(rev)
let list = map(split(system(
\ 'git diff --name-status '.a:rev), '\n'),
\ '{"filename":matchstr(v:val, "\\S\\+$"),"text":s:git_status_dictionary[matchstr(v:val, "^\\w")]}'
\ )
call setqflist(list)
copen
endfunction
command! -nargs=1 DiffRev call s:get_diff_files(<q-args>) Ideally @tpope would add a gstatus-esque window that would instantly diff revisions |
Could we traverse through the selection of the staged/unstaged/untracked files in :Gstatus window maybe? |
This is very useful for doing code reviews. Added a |
@bam80, do you know if there is currently an easier way to move from Gdiff(file1) to Gdiff(file2) than just doing |
The only thing missing from making that automatic is information about what
to diff against.
fre. 3. jan. 2020, 19:13 skrev bzinberg <[email protected]>:
… @bam80 <https://github.com/bam80>, do you know if there is currently an
easier way to move from Gdiff(file1) to Gdiff(file2) than just doing
:diffoff, closing one of the split windows, opening file2 in the
remaining window, and running :Gdiff?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#132?email_source=notifications&email_token=AAAN363O5SPCCGPJLLR7WVLQ3553FA5CNFSM4ALCQ622YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIBXQQY#issuecomment-570652739>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAN364NOOGMQSFZTMOUTO3Q3553FANCNFSM4ALCQ62Q>
.
|
I'll need that information as well to finish |
What to diff against is now available in the quickfix context. Here's a simple usage example. function DiffCurrentQuickfixEntry() abort
cc
let qf = getqflist({'context': 0, 'idx': 0})
if get(qf, 'idx') && type(get(qf, 'context')) == type({}) && type(get(qf.context, 'items')) == type([])
let diff = get(qf.context.items[qf.idx - 1], 'diff', [])
for i in reverse(range(len(diff)))
exe (i ? 'rightbelow' : 'leftabove') 'vert diffsplit' fnameescape(diff[i].filename)
wincmd p
endfor
endif
endfunction |
Will this ever be part of the plugin as a mapping or command? It works, but it's a bit problematic if you do |
Thanks @tpope, this is awesome! |
Like I said:
I think it should start its life as an external addon. When the bugs are worked out, we can talk pull request. |
Just wanted to say: this is great!! thanks! |
Anyone brave? :) |
Here's code that I use to achieve this: command! DiffHistory call s:view_git_history()
function! s:view_git_history() abort
Git difftool --name-only ! !^@
call s:diff_current_quickfix_entry()
" Bind <CR> for current quickfix window to properly set up diff split layout after selecting an item
" There's probably a better way to map this without changing the window
copen
nnoremap <buffer> <CR> <CR><BAR>:call <sid>diff_current_quickfix_entry()<CR>
wincmd p
endfunction
function s:diff_current_quickfix_entry() abort
" Cleanup windows
for window in getwininfo()
if window.winnr !=? winnr() && bufname(window.bufnr) =~? '^fugitive:'
exe 'bdelete' window.bufnr
endif
endfor
cc
call s:add_mappings()
let qf = getqflist({'context': 0, 'idx': 0})
if get(qf, 'idx') && type(get(qf, 'context')) == type({}) && type(get(qf.context, 'items')) == type([])
let diff = get(qf.context.items[qf.idx - 1], 'diff', [])
echom string(reverse(range(len(diff))))
for i in reverse(range(len(diff)))
exe (i ? 'leftabove' : 'rightbelow') 'vert diffsplit' fnameescape(diff[i].filename)
call s:add_mappings()
endfor
endif
endfunction
function! s:add_mappings() abort
nnoremap <buffer>]q :cnext <BAR> :call <sid>diff_current_quickfix_entry()<CR>
nnoremap <buffer>[q :cprevious <BAR> :call <sid>diff_current_quickfix_entry()<CR>
" Reset quickfix height. Sometimes it messes up after selecting another item
11copen
wincmd p
endfunction Basically, after you select a commit you want to preview, call |
This is amazing! @kristijanhusak is there a way to diff with a certain commit rather than just the last one? |
@MosheM123 this is for any commit. Just select a commit from |
I was trying to get away from I wasn't able to find a workaround for this, as the typical solution in your shell is to use Anybody found a workaround for this? I wil really apreciate it. |
Git's own solution to this is |
This cribs code from tpope/vim-fugitive#132 (comment) to make difftool and mergetool a bit more useful. Note that git difftool launching "Git difftool" is not that helpful, since the arguments aren't forwarded.
Based on this discussion, I came up with a small plugin for |
When I'm staging a commit, I usually open
:Gstatus
and run down the diffs (withD
) staging things. Moving to the next diff is a complicated procedure, something like^WP^ND
. It feels ripe for an Unimpaired-style binding, such as]g
to go to the next diff, and[g
to go to the previous. Looking at fugitive.vim, though, I can't decide how best to implement such a thing. Unlike the Quickfix List, for instance, there's no notion of a "cursor" or "current file" in the:Gstatus
window except for the actual cursor, which only exists when the buffer is open, and is ambiguous if it's open in multiple windows.Any thoughts?
The text was updated successfully, but these errors were encountered: