gitvimgit-mergevimdiffmergetool

Configuring vimdiff splits with specific statusline / line-numbers


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

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

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


Solution

  • 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)