68

I am using vim with the fugitive extension. It has a :Gdiff command which brings you into vimdiff mode, but what is the right/quick way to close/quit vimdiff mode?

I.e., let's say I am editing the file FooBar.txt under Git repository. I fire up :Gdiff, review my changes in vimdiff, and then I want to get back and continue editing FooBar.txt or any other file :)

UPDATE1: I'm going to give these quick combos a try next working day :)

"vimdiff current vs git head (fugitive extension)
nnoremap <Leader>gd :Gdiff<cr> 
"switch back to current file and closes fugitive buffer
nnoremap <Leader>gD :diffoff!<cr><c-w>h:bd<cr>

UPDATE2: My current mappings (closes diff window only!)

"vimdiff current vs git head (fugitive extension)
nnoremap <Leader>gd :Gdiff<cr> 
"switch back to current file and closes fugitive buffer
nnoremap <Leader>gD <c-w>h<c-w>c

Also, please help me decide if the following should be an anwser: https://stackoverflow.com/a/15975201/275980

3
  • 1
    gDWorks for me without the :diffoff!<cr>.
    – blueyed
    Apr 4, 2011 at 13:02
  • 2
    Just focusing on the diff window and :q closing it seems to do the trick. It'd be nice if there were an easy way to do it from either window though. Feb 20, 2014 at 16:43
  • It seems that most if not all the answers are Fugitive-plugin-specific, and only partially work with a more plain Vim configuration.
    – MarkHu
    May 4, 2018 at 22:17

15 Answers 15

59

You can execute windo set nodiff noscrollbind and then close the second window.

Update: there is a diffoff command. Use windo diffoff, not what I wrote in previous line.

6
  • 8
    also :diffoff! do the same, right? I was pointed to this command by Tony M. from vim_use group.
    – wik
    Apr 25, 2010 at 13:11
  • 6
    That won't close the window that was opened by :Gdiff, does it?
    – blueyed
    Apr 4, 2011 at 13:03
  • @blueyed Yes, it won't. I don't use fugitive, but diff mode created with VCSVimDiff (VCSCommand plugin) is replaced with non-diff mode (that was active before VCSVimDiff was run) if you run :bw` on the second buffer. It is very convenient, but it is VCSCommand plugin's own feature, not something that vim provides out of the box. You can create an autocommand with similar functionality in your vimrc if you want.
    – ZyX
    Apr 4, 2011 at 15:21
  • @BjornTipling What does not work? diffoff disables vimdiff mode no matter which plugin launched it.
    – ZyX
    Oct 14, 2012 at 13:50
  • 3
    @BjornTipling what I personally don't like about <C-W><C-O> is that it closes all windows, including git status window which is useful to when you doing some deeper investigation, i.e. there is <S-D> map in git status window that also opening diff mode on highlighted file
    – wik
    Mar 5, 2013 at 16:32
40

According to: https://github.com/tpope/vim-fugitive/issues/36

Close the other window. The easiest way to do this if you haven't shifted focus to it is <C-W><C-O>, which means "make this Window the Only window."

4
  • 3
    IMHO this should be the chosen Answer
    – lkraav
    Feb 11, 2012 at 21:22
  • 10
    This would cause problems if you had multiple windows open before entering Gdiff, though--Gdiff only adds a buffer next to the original one, without closing any others. You'd have to re-open everything else you were working on.
    – matthias
    Aug 13, 2012 at 23:01
  • 3
    which isn't quite useful when you do diffs from git status window, since it closing all windows...
    – wik
    Mar 11, 2013 at 16:14
  • Gdiff opens another buffer (tab) with split windows. So this will not work.
    – Geoffrey
    Jul 31, 2017 at 1:43
13

I had no luck with diffoff, but I just learned that :Gedit with no argument will bring you back to the working-directory version of the file, as opposed to some earlier version you were reviewing.

And as q (no need for :q) will close the diff sidebar, you can do q followed by :Gedit to get rid of the sidebar and then go back to the current version of the file.

4
  • 4
    q will start recording. So not sure what kind of 'q' you're using. Maybe that's a gui vim thing or something.
    – Bjorn
    Oct 14, 2012 at 17:22
  • Some plugins remap q, in a given buffer only (map <buffer> q ZZ or whatever), to close that buffer. For me, that happens in the Fugitive git blame "sidebar". Don't remember anymore if that's also used in any diff views.
    – Henrik N
    Oct 16, 2012 at 6:30
  • The default behaviour of :Gedit may be changed. Now it will edit the corespoding file in the index instead of the working tree file.
    – Bohr
    Jun 20, 2013 at 1:32
  • @systemovich This answer proposes first doing :q (or just q) to close the diff sidebar.
    – Henrik N
    Jul 31, 2017 at 8:08
4

None of the above solutions worked for me. Ended up doing this instead:

nnoremap <Leader>D :Gedit<CR><C-w>h :q<CR><C-w>k

1
  • 1
    Just figured this: nnoremap g<C-q> ZZ:Gedit<CR> (see my own question of today). I think it's somewhat better because it avoids moving between windows.
    – sehe
    Nov 5, 2013 at 15:10
4

This works fine for me, combining some of the existing ideas here:

function! MyCloseDiff()
  if (&diff == 0 || getbufvar('#', '&diff') == 0)
        \ && (bufname('%') !~ '^fugitive:' && bufname('#') !~ '^fugitive:')
    echom "Not in diff view."
    return
  endif

  " close current buffer if alternate is not fugitive but current one is
  if bufname('#') !~ '^fugitive:' && bufname('%') =~ '^fugitive:'
    if bufwinnr("#") == -1
      b #
      bd #
    else
      bd
    endif
  else
    bd #
  endif
endfunction
nnoremap <Leader>gD :call MyCloseDiff()<cr>
4

An alternative to <C-W><C-O>, if you have multiple windows, would be move to the other diff window and do <C-W>c, which close only one window.

If you close the wrong diff window do a :Gedit

Be careful and don't confuse <C-W>c with <C-W><C-C>

1
  • That's similar to what I ended up doing in my gD mapping: nnoremap <Leader>gD <c-w>h:bd<cr>
    – wik
    Apr 13, 2013 at 22:28
4

I've found a simple solution for this. You can check it here: https://gist.github.com/radmen/5048080

" Simple way to turn off Gdiff splitscreen
" works only when diff buffer is focused
if !exists(":Gdiffoff")
  command Gdiffoff diffoff | q | Gedit
endif
1
  • I'm liking this one. Ex commands FTW again. I think I'll be using this
    – sehe
    Nov 5, 2013 at 15:13
1

Check the vimdiff toggling between diffthis and diffoff here at this page.

The code:

nnoremap <silent> <Leader>df :call DiffToggle()<CR>

function! DiffToggle()
    if &diff
        diffoff
    else
        diffthis
    endif
:endfunction
0
1

Method 1:

  • open a compare by:

:windo diffthis

  • close it by:

:windo diffoff

Method 2:

I recommend just using the most simple command: :q<CR>

when you want to do it quickly, add the mapping:

" Set mapleader
let mapleader = ","
let g:mapleader = ","

and

" Quickly close the current window
nnoremap <leader>q :q<CR>

It works well for me. Exit vimdiff just by ,q, because normally your cursor in the old file.

0

this is what I have to leave the vimdiff windows after using :Gdiff

nnoremap gD :q!<CR> :Gedit!<CR>
1
  • I believe this will close the actual file and have you end up editing the temporary diff file, where you'll end up losing all of your changes. That is if you never moved your cursor over to the diff.
    – Bjorn
    Oct 14, 2012 at 17:19
0

noremap <leader>do :diffoff \| windo if &diff \| hide \| endif<cr>

Quite diff mode and close other diff windows. (Note: fugitive will auto delete its hidden buffers.)

0

My function will work both from diff window and file window. But probably won't handle itself with multiple diffs opened. For that you'll need to use fugitive#buffer(n).path() to scan and match.

command! Gdiffoff call Gdiffoff()
function! Gdiffoff()
    let diffbufnr = bufnr('^fugitive:')
    if diffbufnr > -1 && &diff
        diffoff | q
        if bufnr('%') == diffbufnr | Gedit | endif
        setlocal nocursorbind
    else
        echo 'Error: Not in diff or file'
    endif
endfunction

Add a key binding:

nnoremap <silent> <leader>gD :Gdiffoff<CR>
0

Yet another way. What I have in fugitive.vim - first save some info (s:gitbufname) when diff starts:

function! s:Diff(vert,...) abort
  call sy#toggle()
  let s:startcol = winwidth(0)
  let &columns=(winwidth(0) * 2 - 20)
...
    if getwinvar('#', '&diff')
      let s:gitbufname = bufname("%")
      wincmd p
      call feedkeys(winnr."\<C-W>w", 'n')
    endif
...
endfunction

and later when leaving the buffer switch window to the saved buffer and restore:

augroup fugitive_diff
autocmd!
autocmd BufWinLeave *
  \ if s:can_diffoff(+expand('<abuf>')) && s:diff_window_count() == 2 |
  \   if exists('s:gitbufname') && winnr() != bufwinnr(s:gitbufname) |
  \     let nr = bufnr("%") | exe bufwinnr(s:gitbufname).'wincmd w' | exe 'buf'.nr |
  \   endif |
  \   call s:diffoff_all(getbufvar(+expand('<abuf>'), 'git_dir')) |
  \   call sy#toggle() |
  \   call airline#load_theme() | call airline#update_statusline() |
  \   let &columns=s:startcol |
  \ endif
...
0

Was using the code below based on https://stackoverflow.com/a/15113951/10999673 :

    if !exists(":Gdiffoff")
        command Gdiffoff bw! fugitive://*
    endif

but it gave me an error "E93: more than one match for ..." in a 3 way diff, so i instead used the answer from https://stackoverflow.com/a/4867969/10999673 and finally have this:

function! GetBufferList()
    return filter(range(1,bufnr('$')), 'buflisted(v:val)')
endfunction

function! GetMatchingBuffers(pattern)
    return filter(GetBufferList(), 'bufname(v:val) =~ a:pattern')
endfunction

function! WipeMatchingBuffers(pattern)
    let l:matchList = GetMatchingBuffers(a:pattern)

    let l:count = len(l:matchList)
    if l:count < 1
        echo 'No buffers found matching pattern ' . a:pattern
        return
    endif

    if l:count == 1
        let l:suffix = ''
    else
        let l:suffix = 's'
    endif

    exec 'bw ' . join(l:matchList, ' ')

    echo 'Wiped ' . l:count . ' buffer' . l:suffix . '.'
endfunction

command! -nargs=1 Gdiffoff call WipeMatchingBuffers('fugitive://')

I just tweaked, copied and pasted the code into my .vimrc

0

Running :Gwrite after merging to your satisfaction will close the other two diff panes in addition to updating the git cache to mark the file as merged.

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.