How do you exit vimdiff mode in vim, specifically, for Fugitive?
Asked Answered
C

15

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://mcmap.net/q/279520/-how-do-you-exit-vimdiff-mode-in-vim-specifically-for-fugitive

Casabonne answered 24/4, 2010 at 7:45 Comment(3)
gDWorks for me without the :diffoff!<cr>.Circumambient
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.Embellishment
It seems that most if not all the answers are Fugitive-plugin-specific, and only partially work with a more plain Vim configuration.Disinfection
C
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.

Campy answered 24/4, 2010 at 8:24 Comment(6)
also :diffoff! do the same, right? I was pointed to this command by Tony M. from vim_use group.Casabonne
That won't close the window that was opened by :Gdiff, does it?Circumambient
@Circumambient 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.Campy
@BjornTipling What does not work? diffoff disables vimdiff mode no matter which plugin launched it.Campy
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"Demand
@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 fileCasabonne
P
42

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

Palpate answered 14/10, 2011 at 2:59 Comment(4)
IMHO this should be the chosen AnswerBarbra
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.Floater
which isn't quite useful when you do diffs from git status window, since it closing all windows...Casabonne
Gdiff opens another buffer (tab) with split windows. So this will not work.Hobart
R
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.

Reactivate answered 18/2, 2011 at 23:3 Comment(4)
q will start recording. So not sure what kind of 'q' you're using. Maybe that's a gui vim thing or something.Demand
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.Reactivate
The default behaviour of :Gedit may be changed. Now it will edit the corespoding file in the index instead of the working tree file.Ptero
@systemovich This answer proposes first doing :q (or just q) to close the diff sidebar.Reactivate
T
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

Tanner answered 24/3, 2011 at 9:15 Comment(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.Wornout
C
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>
Circumambient answered 4/4, 2011 at 13:12 Comment(0)
B
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
Bushhammer answered 27/2, 2013 at 14:0 Comment(1)
I'm liking this one. Ex commands FTW again. I think I'll be using thisWornout
T
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>

Telephonist answered 12/4, 2013 at 15:22 Comment(1)
That's similar to what I ended up doing in my gD mapping: nnoremap <Leader>gD <c-w>h:bd<cr>Casabonne
H
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
Heirship answered 10/1, 2013 at 11:12 Comment(0)
D
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.

Decrement answered 19/10, 2016 at 6:50 Comment(0)
A
0

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

nnoremap gD :q!<CR> :Gedit!<CR>
Ancell answered 5/7, 2012 at 13:17 Comment(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.Demand
P
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.)

Ptero answered 20/6, 2013 at 2:2 Comment(0)
W
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>
Without answered 27/8, 2014 at 15:16 Comment(0)
B
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
...
Begum answered 3/4, 2015 at 0:3 Comment(0)
B
0

Was using the code below based on https://mcmap.net/q/279520/-how-do-you-exit-vimdiff-mode-in-vim-specifically-for-fugitive :

    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://mcmap.net/q/157708/-how-to-delete-multiple-buffers-in-vim 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

Beers answered 1/2, 2019 at 7:27 Comment(0)
I
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.

Interfuse answered 3/4, 2019 at 8:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.