5

Using git how can I load the list of files in the current commit into Quickfix window?

Code Review didn't pass and I want to just fix them one by one.

6

You could use the following function which has the advantage of not changing the state of your local git repo:

function! CommitQF(...)
    " Get the commit hash if it was specified
    let commit = a:0 == 0 ? '' : a:1

    " Get the result of git show in a list
    let flist = system('git show --name-only ' . commit . ' | tail -n +7')
    let flist = split(flist, '\n')

    " Create the dictionnaries used to populate the quickfix list
    let list = []
    for f in flist
        let dic = {'filename': f, "lnum": 1}
        call add(list, dic)
    endfor

    " Populate the qf list
    call setqflist(list)
endfunction

You can call it without argument or with a commit hash as argument (if no argument is specified, the last commit will be used):

call CommitQF("cc5b6a976fde8c9ee66387c91765feb202ba0124")
call CommitQF()

It will use the git show command with the --name-only argument to get the name of the files in the commit. The tail -n +7 command removes the lines which are not a file name in the output of git show.

Then it will create a list of dictionnaries used to populate the quickfix list (see :h setqflist() for more details about that).

You will need to use :copen to open the quicklist after calling the function (or you can add it to the function)


Edit Another possible approach (and probably a better one) using only built in features would be to use these settings:

set makeprg=git\ show\ --name-only\ $*\ \\\|\ tail\ -n\ +7
set efm+=%f

This way you can use :make (for the current commit) or :make fff93a09 (to specify a commit).

The quickfix window will then contain the list of files and you'll be able to navigate to them.

(Of course you might want to create a mapping of something to switch between your usual makeprg and this one)

You can have a look at these help topics:


Second edit @PeterRincker and @LucHermitte made some really nice suggestions in the comments, many thanks to them.

You could use the following one liner:

command -nargs=? -bar Gshow call setqflist(map(systemlist("git show --pretty='' --name-only <args>"), '{"filename": v:val, "lnum": 1}'))

To create a command :Gshow which takes a commit hash as an optionnal argument and populate the quickfix list.

  • Can also use git show --pretty='' --name-only <revision> to remove the commit message information and only show filenames – Peter Rincker Aug 31 '17 at 17:03
  • I would have used map(copy(flist), '{"filename": v:val, "lnum": 1}') instead of the :for loop -- it's always faster, but also much less annoying to debug. – Luc Hermitte Aug 31 '17 at 17:10
  • With @LucHermitte suggestions this could easily be a one liner: command -nargs=? -bar Gshow call setqflist(map(systemlist("git show --pretty='' --name-only <args>"), '{"filename": v:val, "lnum": 1}')) – Peter Rincker Aug 31 '17 at 20:46
  • Thank you both for your suggestion it is indeed much more efficient than my original answer. – statox Sep 1 '17 at 7:36
  • Is there a plug-in that does that? – firedev Sep 1 '17 at 15:05
3

The only thing that comes to mind is

git reset --soft head~1

That would "uncommit" the files, and then browse them in Preview window using vim-fugitive :Gtatus command. Not exactly Quickfix, but it's readable, stores your position and you can stage/unstage from there.

1

Add this to your .vimrc file and you're all set up. This adds files from git diff to the quick fix list:

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()
  let list = map(split(system(
              \ 'git diff --name-status HEAD'), '\n'),
              \ '{"filename":matchstr(v:val, "\\S\\+$"),"text":s:git_status_dictionary[matchstr(v:val, "^\\w")]}'
              \ )
  call setqflist(list)
  copen
endfunction

command! -nargs=0 DiffRev call s:get_diff_files()

Credits: slightly edited

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.