0

I opened several files in vim and then switched git branches. I want to save the versions I have open to the new git branch, for all of them, without having to silence the WARNING: The file has changed since reading it!!! for each of them individually. I am specifically interested in doing this for several files at once. Iterating over all buffers is unacceptable because that will write any file which was previously open in this vim session.

Answers here only help for the single file case and provide no guidance on how to iterate it across many open files without collateral damage.

How do I do it?

10
  • 2
    Just in case you didn't know: This is not the way to do this. You can checkout specific files from another branch or commit to the current branch.
    – muru
    Jul 2, 2019 at 7:03
  • Not a duplicate. I'm asking about the many-files case. Jul 20, 2019 at 1:46
  • 1
    Loop over all windows in all tabs and you have all visible buffers.
    – muru
    Aug 11, 2019 at 7:10
  • 1
    @JacobKopczynski I just saw your edit. I tried to address it, and voted to reopen
    – D. Ben Knoble
    Jan 27, 2020 at 21:54

1 Answer 1

4

Update

It is completely possible to build on the linked duplicate for a specific list of files.

We first extract the old code into a function that will operate on a given filename:

function! ReallyWrite(f) abort
  execute 'buffer' f
  let lastline = line('$')
  let bufcontents = getline(1, lastline)
  edit!
  call setline(1, bufcontents)
  if line('$') > lastline
    execute lastline+1.',$:d _'
  endif
endfunction

Then we write a command to do it for all the files we want:

command -nargs=+ -complete=file ReallyWrite for f in [<f-args>] | call ReallyWrite(f) | endfor

Usage: :ReallyWrite file1 file2

With some simple modifications, ReallyWrite could return to the old buffer after it is finished working. (I think you'd just have to do buffer # at the end of the function.)


This answer is a two-parter:

  1. "Tricking" vim into not caring about the fact that files have changed
  2. Using git properly to avoid this in the first place

Vim

Reading :help :wall tells us that

Vim will warn you if you try to overwrite a file that has been changed
elsewhere.  See |timestamp|.

:help timestamp gives

If you do not want to be asked or automatically reload the file, you can use
this: 
        set buftype=nofile

Now, the problem with buftype=nofile is that the file

will not be written (:help 'buftype')

So, the linked QA provides one answer (save and restore). My solution would be to set all buffers to nofile and then use :w filename (which should still work, according to the docs):

argdo set buftype=nofile | execute 'write' bufname('%')

except that, for some reason, the docs don't seem to be correct: the above command errors for each argument, even though :write filename is supposed to work. :write othername works, but you cannot write to the buffer name.

So I would use the linked answer.

Git

I'm not sure how on-topic this part is, but it's an answer to the question, if a bit of a frame challenge.

You want to get (some of) the files in one branch (to_update) to have identical contents to the corresponding files on another branch (stable).

  1. Checkout the to_update branch
  2. Choose a strategy:
    • Merge the branches: git merge stable. You don't have control over which files change, and they won't be identical post-merge, but you do get the contents from the stable branch (integrated with to_update).
    • Checkout the files on another branch: git checkout stable [files...]. This makes files exactly as they are in stable, and lets you pick which files. No vim reloading necessary.

Caveat: if you have already edited the files, then you switch branches, you have a different problem. You wouldn't be allowed to switch branches if there were conflicts, so the vim method should work fine. If there were conflicts, do git stash, the use the second strategy for git, the git stash apply (followed by git stash drop if you're satisfied).

If you wish to edit the files that changed, you can do some parsing to get a list of changed files. I do this with my git-ed script.

1
  • I virtually always want this in the situation you mention under "Caveat", in which case git can only do it as an awkward kludge. Aug 1, 2019 at 20:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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