1

I'm trying to set up git mergetool to spawn vimdiff with the following splits (and a configuration customized to each split):

  • Splits from the following buffers $LOCAL, $BASE, $REMOTE, & $MERGED (horizontal) [done]
  • Show line-numbers per split [Todo]
  • Display only the name of the buffer variable in these three splits: $LOCAL, $BASE, $REMOTE. [Todo]
  • The $MERGED split statusline should show the filename from %t [the $MERGED split is done]

I used this git configuration in my local repo:

git config merge.tool vimdiff
git config mergetool.vimdiff.cmd 'vim +"set number" +"set statusline=%t" -d -c "wincmd J" -O $MERGED $BASE $REMOTE $LOCAL'
git config merge.conflictstyle diff3
git config mergetool.prompt false
  • In the configuration above, a status line substring should be displayed per-split but I can't find the right way to build a regex to reduce the filename in the statusline down to just one of the three desired buffer variable names (i.e. "BASE", "REMOTE", or "LOCAL"). A regex isn't required, but it seems like a promising option.
  • Line numbers are only showing up in one split, but I want them in all four.

After much googling and many experiments, I still can't coerce vimdiff into showing the status line / numbers I want... I am not using a statusline plugin such as vim-powerline. How do I configure my git options to spawn vimdiff the way I need?

I included a screen capture of my existing git mergetool splits.

vimdiff_4_panes

Mike Pennington
  • 41,899
  • 19
  • 136
  • 174

1 Answers1

5

Adding line numbers for every split

In this command,vim +"set number" ... -O $MERGED $BASE $REMOTE $LOCAL, looks like vim intenally first creates the splits and then executes the set option. Refer: vim -c option.

There are 2 options to overcome this.

  1. Use --cmd option: If we use, vim --cmd "set number" -O $MERGED $BASE $REMOTE $LOCAL, set number is applied before creating the splits. In fact, it is applied even before reading the .vimrc file. (Refer: vim --cmd option). It might cause concern if we have a overriding config in .vimrc like set nonumber.
  2. Create splits manually: Instead of -O option, we can manually create the splits. This way after the -c option is applied, the splits will be created. We will send the file parameters in the reverse order as below:
    vim +"set number" +"vs $LOCAL" +"vs $BASE" +"vs $MERGED" +"wincmd J" $REMOTE
    
    But now we need another option (diff this) to enable diff in all splits, since -d only applies to the files passed directly in the command line.
    vim +"set number" +"vs $LOCAL" +"vs $BASE" +"vs $MERGED" +"wincmd J" +"windo 
    diffthis" $REMOTE
    

Modifying the status line

Rather than regex, using static strings looks a more reliable option. We can leverage vim setlocal options to acheive this. So the total command will be

vim +"set number" +"setlocal statusline=REMOTE" +"vs $LOCAL" +"setlocal statusline=LOCAL" +"vs $BASE" +"setlocal statusline=BASE" +"vs $MERGED" +"wincmd J" +"windo diffthis" $REMOTE

Git mergetool config:

git config merge.tool vimdiff
git config mergetool.vimdiff.cmd 'vim +"set number" +"setlocal statusline=REMOTE" +"vs $LOCAL" +"setlocal statusline=LOCAL" +"vs $BASE" +"setlocal statusline=BASE" +"vs $MERGED" +"wincmd J" +"windo diffthis" $REMOTE'
git config merge.conflictstyle diff3
git config mergetool.prompt false

git mergetool output: git mergetool output


Update 1

If it is ok to retain the existing status line or do a simple append of the buffer number of the split, then -S vim option can be used to greatly simplify the command.

git config mergetool.vimdiff.cmd 'vim -d -S "~/.git_merge_vimrc" -O $MERGED $BASE $REMOTE $LOCAL

.git_merge_vimrc contents:

set statusline=%t-Split#%n
wincmd J
windo set number

Note: vim scripts can be used in the source file to print complex status line if that is required. git mergetool output(with sourcefile)

Prasanna
  • 2,390
  • 10
  • 11
  • I truly wish there was a better way to configure `mergetool.vimdiff.cmd` because by removing the `vim -O` option we now have so many different `--cmd` options that vim throws `Too many "+command", "-c command" or "--cmd command" arguments` if I try adding **any** other `+"set foo"` options. – Mike Pennington Oct 26 '20 at 14:38
  • Also, I tweaked your vimdiff command a bit... I settled on: `vim +"set number" +"setlocal statusline=\$REMOTE-Split_#3" +"vs $LOCAL" +"setlocal statusline=\$LOCAL-Split_#2" +"vs $BASE" +"setlocal statusline=\$BASE-Split_#1" +"vs $MERGED" +"wincmd J" +"setlocal statusline=%t-Split_#4" +"windo diffthis" $REMOTE` for now – Mike Pennington Oct 26 '20 at 14:39
  • @MikePennington, please check if the Update suits your use case better. The status line might vary from your expectation. I am using the buffer no to suffix and the no is based on the order given in `-O` option. – Prasanna Oct 26 '20 at 17:03
  • 1
    The results in [my first comment above](https://stackoverflow.com/questions/64527864/configuring-vimdiff-splits-with-specific-statusline-line-numbers/64534134?noredirect=1#comment114118634_64534134) are better... I definitely need to know what buffer is LOCAL, REMOTE, or BASE. So, realistically we might not be able to get rid of all the individual vim CLI commands but I wish we could – Mike Pennington Oct 26 '20 at 17:06