165

When comparing files, and updating a source code repository, I like to use vimdiff. To copy changes made from one file to the other, I usually use a key sequence like this:-

Shift + V (select line)
k or j; { or }; Up or down arrow keys (select more lines)
y  (copy selected lines)
Ctrl + w, left/right arrow (move to other pane)
p (paste lines)

Vim, being the master of keyboard shortcuts, should surely have an easier way of performing this same task. Is there one? What do you use to manually update source-code changes?

Alex Leach
  • 7,910
  • 2
    Thanks for putting my vague sense of "this isn't what it should be" into a meaningful question. The answer elicited is something I should have learned a long time ago. – Caleb Oct 24 '12 at 12:21
  • 1
    Best answers for your question are here: http://stackoverflow.com/questions/5288875/vimdiff-what-are-the-most-frequently-used-commands-shortcuts-that-could-get-a-n – erik Oct 08 '13 at 17:53

1 Answers1

265

do (diff obtain) and dp (diff put) is what you need. Here is a small list of other helpful normal mode commands in this context.

]c               - advance to the next block with differences
[c               - reverse search for the previous block with differences
do (diff obtain) - bring changes from the other file to the current file
dp (diff put)    - send changes from the current file to the other file
zo               - unfold/unhide text
zc               - refold/rehide text
zr               - unfold both files completely
zm               - fold both files completely

NOTE:
Both do and dp work if you are on a block or just one line under a block in normal mode but not in visual mode. When selecting lines of text in visual mode, you must use the normal commands

  • :'<,'>diffget and
  • :'<,'>diffput.

See also :h copy-diffs.

:diffupdate will re-scan the files for changes.

Hotschke
  • 357
Marco
  • 33,548
  • Just started to use these, but do and dp don't work in Visual modes. – Alex Leach Oct 24 '12 at 13:59
  • @AlexLeach You don't need to mark the text. Placing the cursor on the change or below is sufficient. – Marco Oct 24 '12 at 14:27
  • 4
    True. I found it quite confusing initially, as entire (contiguous) blocks are copied across. That, along with diff mode's auto-hiding of identical lines, I found myself thinking "What the hell just happened?", before triple-checking each move, in both panes. Say you've changed the indentation on one of the files; then I imagine everything will be moved across. For finer-grained control (i.e. Visual selection), I found that the full commands :[range]diffget and :[range]diffput are needed. – Alex Leach Oct 24 '12 at 15:03
  • 9
    You can use visual mode together with diffget and diffput: ① Enter visual mode and mark some text/lines. ② Then type :diffput to push the selected lines to the other file or :diffget to get the selected lines from the other file. – erik Oct 08 '13 at 17:46
  • 1
    Thanks for the comment about putting the cursor below - I was trying from above and do didn't work – hgolov May 01 '15 at 06:54
  • 8
    Hi, does anyone know if there is an equivalent of "do" (obtain difference) for JUST one line? Let's say you have a block of codes (more than one line) that are different, "do" with cursor either at any line of these codes for just the line below these code will obtain difference for the whole block of code --- But I just want to obtain difference for ONE line. Every time I have to visually select this line, followed by "diffget", a bit tedious ... – wiswit May 28 '15 at 09:37
  • 19
    It's important to note that the undo command will only work in the buffer that was changed, so if you use dp and change your mind, you need to switch to the other buffer to undo. – Random832 Jun 11 '15 at 18:10
  • Does anybody know how to do 'do' for all areas of the file? or selected block marked by characters? Everytime I copy from the other file, I keep pressing ]c do ]c do ]c do .. but it should be possible to do this with just a couple of keys. Of course I can exit vimdiff and just do 'cp file1 file2' but usually I'm doing diff inside foreach loop and I don't want to get ouf of the loop. ==> https://stackoverflow.com/questions/6257260/use-vimdiff-to-replace-entire-file/6260060 mimsugara's commend works. – Chan Kim Aug 09 '17 at 06:04
  • 1
    @wiswit: V to select the whole line, then do works to copy over a specific line in current vim (8.0), for whatever it's worth. – dannysauer Apr 19 '19 at 20:34
  • @wiswit I had this question too (drove me nuts). If you look at :help diffget you will see that diffget and diffput both take a range argument but that do and dg do not. So the simplest way is to use . (range specifier for current line) as follows: :.diffget. FWIW V followed by do as suggested above doesn't work on my system, it just deletes the current line and enters insert mode. However, V:diffget does work (seems to automatically insert the current selection as the range argument). – Cole Jun 22 '23 at 05:20
  • Note: to save typing you can use diffup or diffu instead of diffupdate – Cole Jun 22 '23 at 05:24