69

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

Community
  • 1
  • 1
wik
  • 2,462
  • 1
  • 24
  • 29
  • 1
    `gD`Works for me without the `:diffoff!`. – blueyed Apr 04 '11 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. – Aaron Gibralter Feb 20 '14 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 04 '18 at 22:17

15 Answers15

61

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.

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
ZyX
  • 52,536
  • 7
  • 114
  • 135
  • 8
    also :diffoff! do the same, right? I was pointed to this command by Tony M. from vim_use group. – wik Apr 25 '10 at 13:11
  • 6
    That won't close the window that was opened by `:Gdiff`, does it? – blueyed Apr 04 '11 at 13:03
  • @blueyed Yes, it won't. I don't use fugitive, but diff mode created with `VCSVimDiff` ([VCSCommand](http://www.vim.org/scripts/script.php?script_id=90) 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 04 '11 at 15:21
  • @BjornTipling What does not work? `diffoff` disables vimdiff mode no matter which plugin launched it. – ZyX Oct 14 '12 at 13:50
  • It doesn't close the windows and get the the user back to where they were before typing Gdiff, @jtriley's answer does that. This is what the original question wanted: "and then I want to get back and continue editing FooBar.txt" – Bjorn Oct 14 '12 at 16:30
  • 3
    @BjornTipling what I personally don't like about is that it closes all windows, including git status window which is useful to when you doing some deeper investigation, i.e. there is map in git status window that also opening diff mode on highlighted file – wik Mar 05 '13 at 16:32
41

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."

jtriley
  • 591
  • 4
  • 5
  • 3
    IMHO this should be the chosen Answer – lkraav Feb 11 '12 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 '12 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 '13 at 16:14
  • Gdiff opens another buffer (tab) with split windows. So this will not work. – Geoffrey Jul 31 '17 at 01: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.

Henrik N
  • 15,786
  • 5
  • 82
  • 131
  • 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 '12 at 17:22
  • Some plugins remap `q`, in a given buffer only (`map 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 '12 at 06: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 '13 at 01:32
  • @systemovich This answer proposes first doing `:q` (or just `q`) to close the diff sidebar. – Henrik N Jul 31 '17 at 08:08
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
sehe
  • 374,641
  • 47
  • 450
  • 633
radmen
  • 1,584
  • 9
  • 13
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>

José Luis
  • 3,713
  • 4
  • 33
  • 37
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
    Just figured this: `nnoremap g ZZ:Gedit` (see [my own question of today](http://stackoverflow.com/questions/19789829/leave-diff-view-with-fugitive#comment29421052_19789969)). I think it's somewhat better because it avoids moving between windows. – sehe Nov 05 '13 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>
blueyed
  • 27,102
  • 4
  • 75
  • 71
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
Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
aemonge
  • 2,289
  • 1
  • 24
  • 26
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.

tversteeg
  • 4,717
  • 10
  • 42
  • 77
jack guan
  • 331
  • 2
  • 12
0

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

nnoremap gD :q!<CR> :Gedit!<CR>
Adolfo Abegg
  • 765
  • 7
  • 15
  • 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 '12 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.)

Bohr
  • 1,566
  • 1
  • 16
  • 21
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>
rafi
  • 1,648
  • 2
  • 18
  • 23
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
...
cc9cii
  • 1
  • 1
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

wisefool
  • 324
  • 2
  • 3
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.

Caleb
  • 5,084
  • 1
  • 46
  • 65