35

I'd like to open a file from another branch in the current git repository. I have seen this SO question, but the suggestions for combining it with Vim are cumbersome (pipe to Vim, open stdin, set filetype, etc. manually). Is there a simpler way that retains syntax highlighting, filetype settings, etc.?

If it helps:

  • I have the fugitive plugin installed (though rarely used).
  • I don't need to modify it.

The file can be the file for the currently open buffer, or a different one.

48

You can use :Gedit/:Gsplit/:Gvsplit/... with the form {revision}:{filename}

:Gedit branch:/foo/bar.c

Note: If the file is the same as the current file you can abbreviate the command like so: :Gsplit branch:%.

It is often the case that a diff of the current file is preferred than just opening the file on a different branch. You can do this via :Gdiff {branch}.

For more help see:

:h fugitive-:Gedit
:h fugitive-revision
:h fugitive-:Gdiff
:h c_%

You may also want to check out Vimcasts episodes in the Fugitive Series.

  • Beautiful! Curious: what happens if I modify a file so opened? – muru Jun 28 '15 at 2:34
  • 1
    @muru You will notice that the buffer is opened up in a read only buffer (probably notice an [RO] in the status line). – Peter Rincker Jun 28 '15 at 2:38
  • yep, it's there. – muru Jun 28 '15 at 2:42
  • fugitive needs the path from the root of the repository. The answer already cover this, but I wrongly assumed that fugitive could understand when we are in a particular subdirectory of the repo. – Paschalis May 23 '16 at 10:52
  • amazing.. first time using fugitive.. even though I had it installed for a long time :) – alpha_989 May 26 '18 at 19:07
14

This is a little more broad than what OP asked, but for people not wanting to use plugins, and possibly other revision control systems, this little snippet tends to work fairly well:

:new
:r! git show branch:file
:1d

It creates a new window and shows the file there by reading the output of the given command into the new buffer. This of course works with any external command, not just git.

Example for bzr (where REV syntax can specify a branch):

:new
:r! bzr cat -r REV file
:1d

Example for hg (not sure about branches in hg; don't use it enough)

:new
:r! hg cat -r REV file
:1d

Example for svn (

:new
:r! svn cat file@REV
:1d

You would still probably want to set the filetype to get syntax highlighting like in the SO posts, but at least you don't have to mess with piping.

Once opened you can save it under a new name with :w filename or :saveas filename, since Vim won't have a filename for it yet. If you don't want to be able to edit it, you can also throw in a :setlocal readonly and/or :setlocal nomodifiable.

-Edit: Automatic Filetype-

It's a little more work, but you can ask Vim to guess the filetype with

:filetype detect

But, since Vim doesn't have a name yet, this doesn't always work well (for example, I pulled in some C code and it guessed filtype=conf.

We can give it a name by saving it, but we don't want to overwrite a possibly existing file. We can also just set the filename (Thanks @PeterRincker!), but again, we don't want to risk collisions. Since it is unlikely that a file exists that is both the branchname and filename together, we'll concatenate them with some arbitrary separator

:exe "silent file " . "branch" . "-" . "file"
:filetype detect

Where "file" is replaced with the actual filename and "branch" with the branch name

Of course, at this point we are almost writing a plugin ;-)

Thowing it all together, here it is as a git specific function you could drop in your vimrc:

function! GitFile(branch,file)
    new
    exe "silent r! git show " . a:branch . ":" . a:file
    1d
    exe "silent file " . a:branch . "-" . a:file
    filetype detect
    setlocal readonly     "don't allow saving
    setlocal nomodified   "allow easy quitting without saving
    setlocal nomodifiable "don't allow modification
endfunction

which you could wrap in a command or call directly e.g. call GitFile("whateverBranch","myfile.c"). You'll get a new window with a buffer named whateverBranch-myfile.c

  • And can I get it to detect filetype, syntax, etc. automatically with this method? – muru Jun 28 '15 at 2:44
  • Sadly not without some more work; I updated the post – John O'M. Jun 28 '15 at 2:45
  • 1
    I do recommend using the plugin method from @PeterRinker's post if you can. It should do a lot of the nice things you'd like. I mostly wanted to show that one needn't leave the editor nor deal with the hassles of piping to get the data, and I know that there are some people who hate having to use plugins. – John O'M. Jun 28 '15 at 2:57
  • 1
    I just added a bit to be able to detect filetype. It is no longer something you'd want to just type on-the-fly, but could work as an easy addition to a .vimrc. Using a specific plugin will still probably work better. – John O'M. Jun 28 '15 at 3:22
  • You might want to look into using :file to name your file instead of having a temporary file. See :h :file – Peter Rincker Jun 28 '15 at 5:06

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.