Vim: Show current git branch in lightline status line without fugitive

21.8k Views Asked by At

I am using lightline.vim and I would like to show the current git branch. At the moment, I am doing so using vim-fugitive, however, I do not use this plugin at all, except for showing the git branch in the status line.

My question is:

Is there a way to show the git branch in the status line without using fugitive?

I tried to create a custom function that I hooked to lightline. The function fetched the current git branch using the system vimscript function. It (didn't) work well, except that the status line was refreshed on every keystroke, which broke everything else and made vim unusable. Essentially, the git branch was being fetched using the system function on every keystroke...

So that's not a viable solution. What I "could" do, is create a global variable which says whether or not the git branch was fetched, and prevent the custom function from fetching the branch name again if it was already fetched. Then I could fetch the branch name again every time MacVim loses focus (not sure how to do that using terminal vim). That is not ideal though...

Any ideas on how to solve this problem please?

4

There are 4 best solutions below

3
On BEST ANSWER

Yes, using a global variable is the way to go.

The non-obvious part is how/when to update the value of that variable. An autocmd seems to be the most obvious choice but hooked to what event? BufEnter seems to be a good start.

Now, since you don't use fugitive, how do you switch branches? Outside of Vim? On Vim's command-line?

If you do it on Vim's command-line, :!git checkout foo, you could write a command that takes a branch name as argument to execute the proper shell command and change the value of g:git_branch in one go, without even using an autocmd.

If you do it outside of Vim (<C-z>, :sh, another terminal window or tmux pane, a GUI app…) you will need to find a solid way to notify Vim of that change or use your system() call with an autocmd.

1
On

write the followed code into .vimrc.

    let gitBranch=system("git rev-parse --abbrev-ref HEAD")
    set laststatus=2
    set statusline=%F%m%r%h%w\ [POS=%04l,%04v]\ [%p%%]\ [LEN=%L]
    execute "set statusline +=" . gitBranch

3
On

I have created a plugin which focuses on the function you want.

https://github.com/itchyny/vim-gitbranch

You can get the branch name by gitbranch#name() function.

The code is so small that you can read in a minute.

0
On

I had this same question but I just wanted to stick a few lines in my .vimrc instead of installing a plugin. After reading the other answers and some trial and error I ended up with this:

" ~/.vimrc

fun! GitBranch(file)
    let l:dir = fnamemodify(system('readlink -f ' . a:file), ':h')
    let l:cmd = 'git -C ' . l:dir . ' branch --show-current 2>/dev/null'
    let b:git_current_branch = trim(system(l:cmd))
endfun

augroup GitBranch
    autocmd!
    autocmd BufEnter,ShellCmdPost,FileChangedShellPost * call GitBranch(expand('%'))
augroup END

set rulerformat=%32(%=%{b:git_current_branch}%=%8l,%-6(%c%V%)%=%4p%%%)

I put the branch name in the ruler as I don't use lightline or have the statusline on, but rulerformat has exactly the same syntax as statusline, so it should be fairly simple to find where lightline sets statusline and modify it as needed.

The bottom line of my screen looks like this:

".vimrc" 135 lines --39%--                                         master      53,11      39%

The key part is %{b:git_current_branch}, where b:git_current_branch is a variable local to each buffer so you don't get conflicts if you switch buffers.

The GitBranch function will get the current branch name for the file in the current buffer, even if it's in a different directory, following symlinks in the process.

The branch name is updated when you switch buffers, and after a shell command inside vim (e.g. :!git switch or :!git checkout etc.), and also if you change branches outside of vim (after the W11: Warning ... has changed prompt).

If the file in the buffer is not in a git dir, then the variable is empty, and there is no error; the branch name just disappears. If the file is in a git dir but not tracked then you still get the branch name, but you can probably change that with some extra system() calls in GitBranch if that's not what you want.

This works on vim 8 on Linux but I think Mac might have a different readlink command, and I have no idea about Windows.